Nel mio ambiente Bash utilizzo variabili contenenti spazi e utilizzo queste variabili all'interno della sostituzione dei comandi.
Qual è il modo corretto per quotare le mie variabili? E come devo farlo se questi sono nidificati?
DIRNAME=$(dirname "$FILE")
o cito al di fuori della sostituzione?
DIRNAME="$(dirname $FILE)"
o entrambi?
DIRNAME="$(dirname "$FILE")"
o uso i backtick?
DIRNAME=`dirname "$FILE"`
Qual è il modo giusto per farlo? E come posso verificare facilmente se le virgolette sono impostate correttamente?
Risposta accettata:
In ordine dal peggiore al migliore:
DIRNAME="$(dirname $FILE)"
non farà quello che vuoi se$FILE
contiene spazi bianchi (o qualsiasi altro carattere$IFS
contiene attualmente) o caratteri glob[?*
.DIRNAME=`dirname "$FILE"`
è tecnicamente corretto, ma i backtick non sono consigliati per l'espansione dei comandi a causa della maggiore complessità durante l'annidamento e dell'elaborazione della barra rovesciata aggiuntiva che avviene al loro interno.DIRNAME=$(dirname "$FILE")
è corretto, ma solo perché si tratta di un'assegnazione a una variabile scalare (non array). Se usi la sostituzione del comando in qualsiasi altro contesto, comeexport DIRNAME=$(dirname "$FILE")
odu $(dirname -- "$FILE")
, la mancanza di virgolette causerà problemi se il risultato dell'espansione contiene spazi bianchi o caratteri glob.DIRNAME="$(dirname "$FILE")"
(tranne per il--
mancante , vedi sotto) è il modo consigliato. Puoi sostituireDIRNAME=
con un comando e uno spazio senza modificare nient'altro, edirname
riceve la stringa corretta.
Per migliorare ulteriormente:
DIRNAME="$(dirname -- "$FILE")"
funziona se$FILE
inizia con un trattino.DIRNAME="$(dirname -- "$FILE" && printf x)" && DIRNAME="${DIRNAME%?x}" || exit
funziona anche se$FILE
's dirname termina con una nuova riga, poiché$()
taglia le nuove righe alla fine dell'output, sia quella aggiunta dadirname
e quelli che potrebbero far parte dei dati effettivi.
Puoi annidare le espansioni dei comandi quanto vuoi. Con $()
crei sempre un nuovo contesto di quotazione, quindi puoi fare cose come questa:
foo "$(bar "$(baz "$(ban "bla")")")"
Tu non voglio provarlo con i backtick.