L'espansione dei parametri con conseguente stringa vuota viene trattata in modo diverso


10

Aggiornare

Qualcuno nella mailing list bug-bash ha confermato si tratta di un bug.


Se qualcuno è interessato, è disponibile una correzione nell'ultimo commit per sviluppare il ramo .


Mentre

bash -c 'echo "${1##*""}"' _ bar

stampa una riga vuota,

bash -c 'echo "${1##*"${1##*}"}"' _ bar

stampe bar .

Non lo capisco ${1##*}si espande in una stringa vuota, quindi "${1##*}"dovrebbe essere trattato così com'è "", ma sembra che bash non la pensi così.

Sembra esserci un consenso su questo tra le altre shimplementazioni popolari :

$ sh -c 'echo "${1##*"${1##*}"}"' _ bar

$ ash -c 'echo "${1##*"${1##*}"}"' _ bar

$ dash -c 'echo "${1##*"${1##*}"}"' _ bar

$ ksh -c 'echo "${1##*"${1##*}"}"' _ bar

$ ksh93 -c 'echo "${1##*"${1##*}"}"' _ bar

$ mksh -c 'echo "${1##*"${1##*}"}"' _ bar

$ posh -c 'echo "${1##*"${1##*}"}"' _ bar

$ yash -c 'echo "${1##*"${1##*}"}"' _ bar

$ zsh -c 'echo "${1##*"${1##*}"}"' _ bar

$

bash (con o senza --posix) è l'unico non conforme a quello:

$ bash -c 'echo "${1##*"${1##*}"}"' _ bar
bar

E senza elementi di elaborazione della sottostringa il comportamento è come previsto:

$ bash -c 'echo "${1##*"${1+}"}"' _ bar

$ bash -c 'echo "${1##*"${2}"}"' _ bar

$ bash -c 'echo "${1##*"${2}"}"' _ bar ''

$ 

Mi chiedo davvero se c'è una spiegazione per questo, che non ho trovato nel manuale. È un bug o un'errata interpretazione dello standard? Questo comportamento è documentato da qualche parte?


PS: So che una soluzione alternativa è annullare la quotazione del PE interno, ma ciò non risponde alla mia domanda e può portare a risultati indesiderati con stringhe contenenti caratteri speciali.


GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)stampa una stringa vuota
William Pursell,

GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)stampa "bar"
William Pursell il

@William testato il 4.4.20 e 5.0.11 ed entrambi stampano "bar"
oguz ismail

Questo sembra essere un problema con l'espansione in generale. Nel mio 4.4.12(3)-release, echo "${BASH##*"${BASH##*}"}"-> /bin/bash. Mentre echo "\${BASH##*"${BASH##*}"}"-> ${BASH##*}e eval echo "\${BASH##*"${BASH##*}"}"-> vuoto.
Jeff Y,

Risposte:


2

Questa non è una risposta

Prima pensavo che ciò fosse dovuto a speciali regole glob, ma alla fine penso che questo sia un bug di bash. I seguenti quattro esempi dovrebbero darti un'idea del perché ritengo che si tratti di un bug:

$ bash -c 'echo "${1##*${1%%bar}}"' _ foobar        # case 1
bar
$ bash -c 'echo "${1##*${1%%foobar}}"' _ foobar     # case 2

$ bash -c 'echo "${1##*"${1%%bar}"}"' _ foobar      # case 3
bar
$ bash -c 'echo "${1##*"${1%%foobar}"}"' _ foobar   # case 4
foobar

Il caso 1 e il caso 3 differiscono tra virgolette. Ma l'espansione dei parametri del modulo ${parameter##word}utilizza le regole di espansione del nome percorso per l'elaborazione word. Quindi, *fooe *"foo"hanno un comportamento identico come i doppi apici in espansione di percorso può essere ignorato a meno che non abbracciano i caratteri speciali del modello ( *, ?, ...). Questo è visto nel seguente esempio:

$ bash -c 'echo "${1##*${2%%b*r}}"' _ 'foobar' 'f*ob*r'
bar
$ bash -c 'echo "${1##*"${2%%b*r}"}"' _ 'foobar' 'f*ob*r'
foobar

Quindi, in questo caso, perché il caso 2 e il caso 4 dovrebbero comportarsi diversamente?


perché i casi 2 e 4 dovrebbero comportarsi diversamente? Nessun motivo, entrambi ${1+}e si ${1+""}espande in una stringa vuota, ma non sono trattati così ${1##*}(vedi la mia ultima modifica). Quindi possiamo dedurre che si tratta di un bug, giusto?
Oguz Ismail,

1
@oguzismail Esatto! Se il caso 1 e il caso 3 si comportano in modo identico, anche il caso 2 e il caso 4 devono comportarsi in modo identico.
kvantour,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.