Espansione della stringa quotata vs non quotata


11
  1. for i in $(xrandr); do echo "$i" ; done
  2. for i in "$(xrandr)"; do echo "$i"; done
  3. for i in "$(xrandr)"; do echo $i; done

Capisco perché 1 differisce da 2. Ma perché 3 fornisce un output diverso da 2? Spiegare anche l'output. Come funzionano le citazioni su newline?



Risposte:


19

Una variabile non quotata (come in $var) o la sostituzione di comando (come in $(cmd)o `cmd`) è l' operatore split + glob in shell tipo Bourne.

Cioè, il loro contenuto è diviso in base al valore corrente della $IFSvariabile speciale (che per impostazione predefinita contiene lo spazio, la scheda e i caratteri di nuova riga)

E quindi ogni parola risultante da quella suddivisione è soggetta alla generazione del nome del file (noto anche come globbing o espansione del nome file ), cioè sono considerati come modelli e vengono espansi all'elenco dei file che corrispondono a quel modello.

Quindi in for i in $(xrandr), $(xrandr)poiché non è racchiuso tra virgolette, è diviso in sequenze di caratteri di spazio, tabulazione e newline. E ogni parola risultante da quella suddivisione viene controllata per trovare i nomi dei file corrispondenti (o lasciata così com'è se non corrispondono a nessun file) e forscorre su tutti.

In for i in "$(xrandr)", non stiamo usando l'operatore split + glob come viene citata la sostituzione del comando , quindi c'è un passaggio nel ciclo su un valore: l'output di xrandr(senza i caratteri di nuova riga finali che comandano le strisce di sostituzione ).

Tuttavia echo $i, $iviene nuovamente citato, quindi il contenuto di $iviene diviso e soggetto alla generazione del nome file e questi vengono passati come argomenti separati al echocomando (e echorestituisce i suoi argomenti separati da spazi).

Quindi lezione imparata:

  • se non si desidera la suddivisione delle parole o la generazione del nome file , citare sempre espansioni variabili e sostituzioni di comandi
  • se si desidera la suddivisione delle parole o la generazione del nome file , lasciarli non quotati ma impostare di $IFSconseguenza e / o abilitare o disabilitare la generazione del nome file, se necessario ( set -f, set +f).

In genere, nell'esempio sopra riportato, se si desidera passare in rassegna l'elenco di parole separato vuoto nell'output di xrandr, è necessario:

  • lasciare $IFSal suo valore predefinito (o disinserirlo) per dividere gli spazi vuoti
  • Utilizzare set -fper disabilitare la generazione nome di file se non sei sicuro che xrandrnon emette alcun *o ?o [personaggi (che sono i caratteri jolly utilizzati nei modelli di generazione di file)

E quindi usa solo l'operatore split + glob (lascia solo la sostituzione dei comandi o l'espansione variabile non quotata) nella inparte del forciclo:

set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done

Se si desidera ciclo nel corso dei (non-vuoto) le linee di xrandruscita, avresti bisogno di set $IFSper il carattere di nuova riga:

IFS='
'

4

Una newline tra virgolette è una newline. Quindi echo "$1"fornisce un singolo argomento della riga di comando da echo, che quindi stampa direttamente le nuove righe.

Una newline non quotata è uno spazio bianco. Quindi echo $1fornisce molti argomenti della riga di comando da eco, che li stampa uno dopo l'altro separati da spazi.


Una newline non quotata è che gli spazi bianchi sono un po 'troppo scorciatoie per essere davvero utili come una spiegazione del comportamento qui IMO.
Stéphane Chazelas,
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.