web-dev-qa-db-fra.com

Quelle est la signification de IFS = $ '\ n' dans les scripts bash?

Au début d'un script shell bash se trouve la ligne suivante:

IFS=$'\n'

Quelle est la signification de cette collection de symboles?

180
Abdul Al Hazred

IFS signifie "séparateur de champ interne". Il est utilisé par le Shell pour déterminer comment effectuer le fractionnement de Word, i. e. comment reconnaître les limites de Word.

Essayez ceci dans un shell comme bash (d'autres shells peuvent gérer cela différemment, par exemple zsh):

mystring="foo:bar baz rab"
for Word in $mystring; do
  echo "Word: $Word"
done

La valeur par défaut de IFS consiste en des espaces (pour être précis: espace, tabulation et retour à la ligne). Chaque caractère peut être une limite de Word. Ainsi, avec la valeur par défaut de IFS, la boucle ci-dessus s'affichera:

Word: foo:bar
Word: baz
Word: rab

En d'autres termes, le Shell pense que les espaces blancs sont une limite de Word.

Maintenant, essayez de définir IFS=: avant d'exécuter la boucle. Cette fois, le résultat est:

Word: foo
Word: bar baz rab

Maintenant, le Shell divise également mystring en mots - mais maintenant, il ne traite que les deux-points comme limite Word.

Le premier caractère de IFS est spécial: il est utilisé pour délimiter les mots dans la sortie lorsque vous utilisez le spécial $* variable (exemple tiré du Advanced Bash Scripting Guide , où vous pouvez également trouver plus d'informations sur des variables spéciales comme celle-ci):

$ bash -c 'set w x y z; IFS=":-;"; echo "$*"'
w:x:y:z

Comparer aux:

$ bash -c 'set w x y z; IFS="-:;"; echo "$*"'
w-x-y-z

Notez que dans les deux exemples, le Shell traitera toujours tous les caractères :, - et ; comme limites de Word. La seule chose qui change est le comportement de $*.

Une autre chose importante à savoir est de savoir comment les "espaces blancs IFS" sont traités . Fondamentalement, dès que IFS inclut des caractères d'espacement, les espaces de début et de fin sont supprimés de la chaîne à fractionner avant de la traiter et une séquence de caractères blancs consécutifs délimite également les champs. Cependant, cela s'applique uniquement aux espaces blancs qui sont réellement présents dans IFS.

Par exemple, regardons la chaîne "a:b:: c d " (espace de fin et deux espaces entre c et d).

  1. Avec IFS=: il serait divisé en quatre champs: "a", "b", "" (chaîne vide) et " c d " (encore une fois, deux espaces entre c et d). Notez les espaces de début et de fin dans le dernier champ.
  2. Avec IFS=' :', il serait divisé en cinq champs: "a", "b", "" (chaîne vide), "c" et "d". Aucun espace blanc avant et arrière nulle part.

Notez que plusieurs espaces blancs consécutifs délimitent deux champs dans le deuxième exemple, contrairement à plusieurs deux points consécutifs (car ce ne sont pas des espaces blancs).

Pour ce qui est de IFS=$'\n', c'est un ksh93 syntaxe également prise en charge par bash, zsh, mksh et FreeBSD sh (avec des variations entre tous les shells). Citant la page de manuel bash:

Les mots de la forme $ 'string' sont traités spécialement. Le mot se développe en "chaîne", avec des caractères d'échappement antislash remplacés comme spécifié par la norme C ANSI.

\n est la séquence d'échappement d'une nouvelle ligne, donc IFS finit par être défini sur un seul caractère de nouvelle ligne.

216
Tblue

À l'intérieur des guillemets simples en dollars, certains caractères sont évalués spécialement. Par exemple, \n est traduit sur une nouvelle ligne.

Ainsi, cette ligne particulière assigne une nouvelle ligne à la variable IFS. IFS, à son tour, est une variable spéciale dans bash: Séparateur de champ interne. Comme man bash dit, il

est utilisé pour le fractionnement de Word après expansion et pour diviser les lignes en mots avec la commande intégrée read. La valeur par défaut est <space><tab><newline>.

23
choroba

Pour faire court, IFS=$'\n' affecter une nouvelle ligne \n à la variable IFS.

$'string' construct est un mécanisme de citation utilisé pour décoder les séquences d'échappement de type ANSI C. Cette syntaxe vient de ksh93, et était portable pour Shell moderne comme bash, zsh, pdksh, busybox sh.

Cette syntaxe n'est pas définie par POSIX, mais a été acceptée pour problème SUS 7 .

15
cuonglm