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.