Au début d'un script shell bash se trouve la ligne suivante:
IFS=$'\n'
Quelle est la signification de cette collection de symboles?
Au début d'un script shell bash se trouve la ligne suivante:
IFS=$'\n'
Quelle est la signification de cette collection de symboles?
Réponses:
IFS
est synonyme de "séparateur de champ interne". Le shell l’utilise pour déterminer comment scinder le mot, c’est-à-dire reconnaître les limites de mot.
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 pour se IFS
compose de caractères d'espacement (pour être précis: espace, tabulation et nouvelle ligne). Chaque caractère peut être une limite de mot. Donc, avec la valeur par défaut de IFS
, la boucle ci-dessus affichera:
Word: foo:bar
Word: baz
Word: rab
En d'autres termes, le shell pense que les espaces sont une limite de mots.
Maintenant, essayez de régler IFS=:
avant d’exécuter la boucle. Cette fois, le résultat est:
Word: foo
Word: bar baz rab
Le shell se divise également mystring
en mots - mais à présent, il ne traite que les deux points comme la limite de mot.
Le premier caractère de IFS
est spécial: il est utilisé pour délimiter des mots dans la sortie lorsque vous utilisez la $*
variable spéciale (exemple tiré du Guide de script de Bash avancé , 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, la coquille continue de traiter tous les personnages :
, -
et ;
que les limites de mots. La seule chose qui change est le comportement de $*
.
Une autre chose importante à savoir concerne le traitement de ce que l'on appelle les "espaces blancs IFS" . Fondamentalement, dès que IFS
les caractères d'espacement sont inclus, les espaces de début et de fin sont supprimés de la chaîne à scinder avant d'être traités et une séquence de caractères d'espacement consécutifs délimite également les champs. Toutefois, cela ne s'applique qu'aux caractères d'espacement 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
).
IFS=:
elle serait divisée 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.IFS=' :'
, il serait divisé en cinq domaines: "a"
, "b"
, ""
(chaîne vide), "c"
et "d"
. Aucun espace de début et de fin nulle part.Notez que plusieurs caractères d'espacement consécutifs délimitent deux champs dans le deuxième exemple, tandis que plusieurs points consécutifs ne le sont pas (car ils ne sont pas des caractères d'espacement).
En ce qui concerne IFS=$'\n'
, qui est une ksh93
syntaxe également pris en charge par bash
, zsh
, mksh
et FreeBSD sh
(avec des variations entre les coquilles). Citant la page de manuel bash:
Les mots de la forme $ 'chaîne' sont traités spécialement. Le mot se développe en "chaîne", avec les caractères d'échappement avec une barre oblique inversée remplacés comme spécifié par la norme ANSI C.
\n
est la séquence d'échappement pour une nouvelle ligne, IFS
finit par être défini sur un seul caractère de nouvelle ligne.
bash
guide de script, ou peu importe. Dans l’ensemble, l’information disponible sur des liens comme celui-ci manque de façon importante. Quoi qu’il en soit, il manque donc deux points cruciaux concernant la division du shell - le globbing et les espaces blancs IFS.
unset IFS
un shell se comporte de manière très différente de IFS=
. Le premier octet dans IFS est également spécial "${named_array[*]}"
- mais cela n’a aucune importance lorsque l’extension n’est pas citée ..
$IFS
est l'une des deux choses principales exécutées lors de l'expansion d'une variable non citée dans le contexte d'une liste (c'est la split
partie de l' split+glob
opérateur). L'autre est globbing. Lorsque vous utilisez le fractionnement du travail, vous devez généralement émettre set -f
pour désactiver la glob
pièce.
$IFS
est également utilisé par la read
commande intégrée
Dans les guillemets simples en dollars, certains caractères sont évalués spécialement. Par exemple, \n
est traduit en nouvelle ligne.
Donc, cette ligne particulière affecte newline à 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 séparer les mots après le développement et pour séparer les lignes en mots avec la
read
commande interne. La valeur par défaut est<space><tab><newline>
.
dollared single quotes
ce qui est différent des simples guillemets simples.
Pour faire court, IFS=$'\n'
attribuez newline \n
à variable IFS
.
$'string'
construct est un mécanisme de citation qui décode les séquences d'échappement de type ANSI C. Cette syntaxe provient ksh93
et est portable shell moderne comme bash
, zsh
, pdksh
, busybox sh
.
Cette syntaxe n'est pas définie par POSIX, mais a été acceptée pour le problème 7 de SUS .
J'ai préféré expliquer $IFS
par l'exemple:
supposons que vous vouliez utiliser cp, mv ou un autre processus de traitement de fichier, IFS est vide par défaut, lorsque vos fichiers ont un caractère méta ou un espace tel que:
Linux Administration.pdf
ou Free Software Fundation.ogg
, bien sûr, vous aurez un problème, car: Linux considère un séparer param et Administartion considèrent un séparateur séparé.Alors bash a built-in variable
, ensuite vous pouvez initialiser à IFS==$(echo -en "\n\b")
, puis bash ignorer tout caractère méta et l'espace entre le nom de fichier, Par exemple:
#!/bin/bash
SAVEIFS=$IFS
IFS=$(echo -en "\n\b")
mymusicdir=~/test/dd
find $mymusicdir -name "*" -execdir rename 's/ /_/g' "{}" +
IFS=$SAVEIFS