for i in $(xrandr); do echo "$i" ; donefor i in "$(xrandr)"; do echo "$i"; donefor i in "$(xrandr)"; do echo $i; done
Capisco perché 1 differisce da 2. Ma perché 3 fornisce un output diverso da 2? Si prega di spiegare anche l'output. Come funzionano le virgolette sulle nuove righe?
Risposta accettata:
Una variabile senza virgolette (come in $var ) o la sostituzione del comando (come in $(cmd) o `cmd` ) è il split+glob operatore in shell tipo Bourne.
Cioè, il loro contenuto è suddiviso in base al valore corrente di $IFS variabile speciale (che per impostazione predefinita contiene i caratteri spazio, tabulazione e nuova riga)
E poi ogni parola risultante da quella divisione è soggetta a generazione di nomi di file (noto anche come globbing o espansione del nome file ), ovvero sono considerati modelli e vengono espansi all'elenco di file che corrispondono a tale modello.
Quindi in for i in $(xrandr) , il $(xrandr) , poiché non è racchiuso tra virgolette, è suddiviso in sequenze di caratteri spazio, tabulazione e nuova riga. E ogni parola risultante da quella divisione viene verificata per i nomi dei file corrispondenti (o lasciata così com'è se non corrispondono a nessun file) e for li scorre tutti.
In for i in "$(xrandr)" , non utilizziamo l'operatore split+glob come sostituzione di comando è quotato, quindi c'è un passaggio nel ciclo su uno valore:l'output di xrandr (senza i caratteri di nuova riga finali che comandano la sostituzione strisce).
Tuttavia in echo $i , $i è di nuovo senza virgolette, quindi di nuovo il contenuto di $i è diviso e soggetto a generazione di nomi di file e quelli vengono passati come argomenti separati a echo comando (e echo restituisce i suoi argomenti separati da spazi).
Quindi lezione appresa:
- se non vuoi dividere le parole o generazione di nomi di file , cita sempre espansioni di variabili e sostituzioni di comandi
- se vuoi dividere le parole o generazione di nomi di file , lasciali senza virgolette ma imposta
$IFSdi conseguenza e/o abilitare o disabilitare la generazione del nome del file, se necessario (set -f,set +f).
Tipicamente, nel tuo esempio sopra, se vuoi scorrere l'elenco vuoto di parole separate nell'output di xrandr , dovresti:
- lascia
$IFSal suo valore predefinito (o deselezionalo) per dividerlo in spazi vuoti - Usa
set -fper disabilitare la generazione del nome file a meno che tu non sia sicuro chexrandrnon genera mai alcun*o?o[caratteri (che sono caratteri jolly utilizzati nei modelli di generazione dei nomi di file)
E poi usa solo l'operatore split+glob (lascia solo la sostituzione del comando o l'espansione della variabile senza virgolette) nel in parte del for ciclo:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Se vuoi scorrere le linee (non vuote). del xrandr output, dovresti impostare $IFS al carattere di nuova riga:
IFS='
'