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$FILEcontiene spazi bianchi (o qualsiasi altro carattere$IFScontiene 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, edirnamericeve la stringa corretta.
Per migliorare ulteriormente:
DIRNAME="$(dirname -- "$FILE")"funziona se$FILEinizia con un trattino.DIRNAME="$(dirname -- "$FILE" && printf x)" && DIRNAME="${DIRNAME%?x}" || exitfunziona anche se$FILE's dirname termina con una nuova riga, poiché$()taglia le nuove righe alla fine dell'output, sia quella aggiunta dadirnamee 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.