Che cos'è l'IFS?


Risposte:


17

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.Input Internal 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.


1
Si noti che IFS viene utilizzato anche per combinare i parametri per l'output. Dalla pagina man bash: "Quando l'espansione avviene tra virgolette doppie, si espande in una singola parola con il valore di ciascun parametro separato dal primo carattere della variabile speciale IFS."
Eric

Si dovrebbe anche notare che mentre 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.
Stéphane Chazelas,

27

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:

  • Se il contesto prevede una sola parola, ad esempio quando la sostituzione è tra virgolette doppie "$foo"o in un'assegnazione variabile x=$foo, la stringa risultante dalla sostituzione viene utilizzata così com'è.
  • Se il contesto prevede più parole, come nel caso della maggior parte delle volte, sulla stringa risultante vengono eseguite altre due espansioni:
    • La stringa è divisa in parole . Qualsiasi carattere che appare in $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).
    • Ogni parola viene trattata come un modello glob ed espansa in un elenco di nomi di file . Ad esempio, 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, rld​␤h(dove ​␤è un carattere nuova riga) e wdy.


Perché hai citato "Indirettamente" in "IFS indirectly determines how ..."?
αғsнιη,

1
@ αғsнιη IFS(direttamente) determina il modo in cui viene suddivisa l'output della sostituzione del comando, che quindi (indirettamente) determina su cosa passa il loop.
Gilles 'SO- smetti di essere malvagio'

5

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.

http://tldp.org/LDP/abs/html/internalvariables.html


0

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.

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.