for i in $(xrandr); do echo "$i" ; done
for i in "$(xrandr)"; do echo "$i"; done
for 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
$IFS
di 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
$IFS
al suo valore predefinito (o deselezionalo) per dividerlo in spazi vuoti - Usa
set -f
per disabilitare la generazione del nome file a meno che tu non sia sicuro chexrandr
non 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='
'