Stavo leggendo questo thread: come passare in rassegna le righe di un file?
Che cosa è IFS? E qual è il suo utilizzo nel contesto di for-loops?
Stavo leggendo questo thread: come passare in rassegna le righe di un file?
Che cosa è IFS? E qual è il suo utilizzo nel contesto di for-loops?
Risposte:
IFSsta per - è un personaggio che separa i campi. Nell'esempio che hai pubblicato, è impostato su new line character ( ); quindi dopo averlo impostato, elaborerà il testo riga per riga. In quell'esempio, potresti cambiare il valore di (in qualche lettera che hai nel tuo file di input) e controllare come il testo verrà diviso.InputInternal Field Separator\nforIFS
A proposito, dalla risposta che hai pubblicato la seconda soluzione è quella consigliata ...
Come notato da @jasonwryan , non lo è Inputma Internal. Il nome è Inputvenuto da awkcui c'è anche OFS- Output Field Separator.
Sera per separatore nella shell Bourne da cui proviene. Nella shell Korn e nella maggior parte delle altre shell tipo Bourne, come è stato ora specificato da POSIX, Sè per Delimitatore (allunga un po 'la tua immaginazione) come A::B:ad esempio è diviso in "A", "" e "B" (nessun extra ""). È diverso da awk' FSo dal sflag di espansione dei parametri di zsh.
IFSnon è direttamente correlato al looping, è legato alla suddivisione delle parole. IFSdetermina indirettamente come l'output del comando viene suddiviso in parti su cui il loop scorre.
Quando si ha una sostituzione variabile non protetta $fooo una sostituzione comando $(foo), ci sono due casi:
"$foo"o in un'assegnazione variabile x=$foo, la stringa risultante dalla sostituzione viene utilizzata così com'è.$IFSè considerato un separatore di parole. Ad esempio IFS=":"; foo="12:34::78"; echo $foostampe 12 34 78(con due spazi tra 34e 78, poiché c'è una parola vuota).foo="*"; echo $foostampa l'elenco dei file nella directory corrente.Per i loop, come molti altri contesti, si aspetta un elenco di parole. Così
for x in $(foo); do …
si spezza $(foo)in parole e tratta ogni parola come un modello glob. Il valore predefinito IFSè spazio, tab e newline , quindi se foostampa due righe hello worlde howdyil corpo del loop viene eseguito con x=hello, quindi x=worlde x=howdy. Se IFSviene esplicitamente modificato per contenere solo una nuova riga, il ciclo viene eseguito per hello worlde howdy. Se IFSviene modificato per essere o, poi il ciclo viene eseguito per hell, w, rldh(dove è un carattere nuova riga) e wdy.
"IFS indirectly determines how ..."?
IFS(direttamente) determina il modo in cui viene suddivisa l'output della sostituzione del comando, che quindi (indirettamente) determina su cosa passa il loop.
A partire dal man bash
IFS Il separatore di campo interno utilizzato per la divisione delle parole dopo l'espansione e per dividere le linee in parole con il comando incorporato read. Il valore predefinito è "<spazio> <tab> <nuova>>.
Questa è una delle variabili interne di Bash. Determina il modo in cui Bash riconosce i campi, o i confini delle parole, quando interpreta le stringhe di caratteri.
Mentre l'impostazione predefinita è uno spazio bianco (spazio, tabulazione e nuova riga), ad esempio, può essere modificato per analizzare un file di dati separato da virgole.
Oltre alle ottime risposte precedenti, vorrei solo aggiungere che IFS è molto utile per l'analisi efficiente e portatile in casi semplici in combinazione con set . Efficiente, perché evita l'uso di subshells e strumenti di generazione come grep o sed:
resolutions="640x480,320x240"
xIFS=$IFS
IFS=','
for res in $resolutions; do
xxIFS=$IFS
IFS='x'
set -- $res
width=$1
height=$2
# handle width and height
IFS=$xxIFS
done;
IFS=$xIFS
Si noti che è necessario archiviare e ripristinare il valore precedente di IFS per evitare rotture indesiderate in altre parti dello script.