Qu'est-ce que l'IFS?

Réponses:

17

IFSreprésente - c'est un caractère qui sépare les champs. Dans l'exemple que vous avez publié, il est défini sur un nouveau caractère de ligne ( ); donc après l'avoir défini, traitera le texte ligne par ligne. Dans cet exemple, vous pouvez modifier la valeur de (en une lettre que vous avez dans votre fichier d'entrée) et vérifier comment le texte sera divisé.Input Internal Field Separator\nforIFS

BTW, d'après la réponse que vous avez publiée, la deuxième solution est celle recommandée ...

Comme @jasonwryan remarqué, ce n'est pas Inputmais Internal. Le nom Inputvient d' awkoù il y a aussi OFS- Output Field Separator.

pbm
la source
1
Notez que IFS est également utilisé pour combiner les paramètres de sortie. À partir de la page de manuel bash: "Lorsque l'expansion se produit entre guillemets, elle se développe en un seul mot avec la valeur de chaque paramètre séparée par le premier caractère de la variable spéciale IFS."
Eric
Il faut également noter que while Sétait pour separator dans le shell Bourne d'où il provenait. Dans le shell Korn et la plupart des autres shell de type Bourne comme cela a été spécifié par POSIX, le Sest pour le délimiteur (étirez un peu votre imagination) car A::B:par exemple est divisé en "A", "" et "B" (sans supplément ""). C'est différent de awk's FSou du sdrapeau d'expansion des paramètres de zsh.
Stéphane Chazelas
27

IFSn'est pas directement lié au bouclage, il est lié au fractionnement de mots. IFSdétermine indirectement comment la sortie de la commande est divisée en morceaux sur lesquels la boucle itère.

Lorsque vous avez une substitution de variable non protégée $fooou une substitution de commande $(foo), il y a deux cas:

  • Si le contexte attend un seul mot, par exemple lorsque la substitution se fait entre guillemets doubles "$foo", ou dans une affectation de variable x=$foo, la chaîne résultant de la substitution est utilisée telle quelle.
  • Si le contexte attend plusieurs mots, ce qui est le cas la plupart du temps, deux extensions supplémentaires sont effectuées sur la chaîne résultante:
    • La chaîne est divisée en mots . Tout caractère qui apparaît dans $IFSest considéré comme un séparateur de mots. Par exemple, IFS=":"; foo="12:34::78"; echo $fooimprime 12 34 ​ 78(avec deux espaces entre 34et 78, car il y a un mot vide).
    • Chaque mot est traité comme un modèle global et développé en une liste de noms de fichiers . Par exemple, foo="*"; echo $fooimprime la liste des fichiers dans le répertoire courant.

Pour les boucles, comme beaucoup d'autres contextes, attendez-vous à une liste de mots. Donc

for x in $(foo); do 

se décompose $(foo)en mots et traite chaque mot comme un motif global. La valeur par défaut de IFSest espace, tabulation et nouvelle ligne , donc si fooimprime deux lignes hello worldet que howdyle corps de la boucle est exécuté avec x=hello, puis x=worldet x=howdy. Si IFSest explicitement modifié pour ne contenir qu'une nouvelle ligne, la boucle est exécutée pour hello worldet howdy. Si IFSest changé pour être o, alors la boucle est exécutée pour hell, ​ w, rld​␤h(où ​␤est un caractère de saut de ligne) et wdy.

Gilles 'SO- arrête d'être méchant'
la source
Pourquoi avez-vous mentionné "indirectement" dans "IFS indirectly determines how ..."?
αғsнιη
1
@ αғsнιη IFS(directement) détermine comment la sortie de la substitution de commande est décomposée, ce qui détermine ensuite (indirectement) ce que la boucle boucle.
Gilles 'SO- arrête d'être méchant'
5

De man bash

IFS Séparateur de champ interne utilisé pour le fractionnement de mots après expansion et pour diviser des lignes en mots avec la commande intégrée read. La valeur par défaut est "<espace> <tab> <newline>".

C'est l'une des variables internes de Bash. Il détermine comment Bash reconnaît les champs ou les limites des mots lorsqu'il interprète les chaînes de caractères.

Par défaut, il s'agit d'espaces (espace, tabulation et nouvelle ligne), mais il peut être modifié, par exemple, pour analyser un fichier de données séparé par des virgules.

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

jasonwryan
la source
0

En plus des excellentes réponses précédentes, permettez-moi d'ajouter que IFS est très utile pour une analyse efficace et portable dans des cas simples en combinaison avec set . Efficace, car évite d'utiliser des sous-coquilles et des outils de frai comme grep ou 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

Notez simplement que nous devons stocker et récupérer la valeur précédente d' IFS pour éviter les ruptures indésirables dans d'autres parties du script.

pmod
la source