comprendre la valeur par défaut d'IFS

10

Dans ma version 4.2.8 de GNU bash, IFS a une valeur par défaut d'espace, de tabulation et de saut de ligne par défaut:

usr@T42 ~ $ echo -n "$IFS" | hexdump -C
00000000  20 09 0a                                          | ..|
00000003
usr@T42 ~ $ 

Y a-t-il une raison pour un tel IFS par défaut? De plus, quels utilitaires utilisent IFS en plus de bash intégré read?

Martin
la source

Réponses:

13

La variable IFS est utilisée chaque fois que le shell exécute une tâche appelée séparation de mots . Les cas les plus courants où cela est utilisé sont après l'expansion des paramètres (par exemple $var) ou la substitution de commandes (par exemple $(some-command)ou les backticks déconseillés) dans une commande. Ici, si l'extension contient des IFScaractères, elle se divise en différents «mots» avant que la commande ne soit traitée. Cela signifie effectivement que ces caractères divisent le texte substitué en différents arguments (y compris le nom de la commande si la variable est spécifiée en premier).

Ainsi, la raison pour laquelle la valeur par défaut IFSest espace, tabulation et saut de ligne est que ce sont les caractères d'espacement qui devraient normalement séparer un mot.

Une façon d'empêcher le fractionnement de mots de se produire est d'utiliser des guillemets doubles autour de l'expansion ( "$var") - en fait, vous l'avez fait dans votre question. Si vous ne le faisiez pas, il n'y aurait pas de sortie echocar il n'aurait pas d'arguments, seulement des caractères séparant les arguments.

Notez également que deux endroits où le fractionnement des mots ne se produit pas après l'expansion des paramètres sont avec une affectation de variable (par exemple var=$othervaret var=$(somecommand)est ok) et dans la [[ ]]construction ( [[ $var = $othervar ]]est ok, mais [ $var = $othervar ]doit être cité).

Enfin, comme un homme sage m'a fait remarquer une fois, une idée fausse commune est que la prévention du fractionnement de mots est la seule raison de citer une variable. Ce n'est pas le cas, la citation empêche également l' expansion des noms de chemin ou l' expansion globale, comme cela est plus communément connu. Si une variable contient des caractères globaux comme *ceux-ci, ceux-ci peuvent être développés en noms de fichiers lorsque la variable est utilisée sans guillemets dans une commande. Par exemple, considérez:

var=*
echo $var

Cela affichera les noms des fichiers dans le répertoire courant.

Comme Stephane le souligne ci - dessous , l'ordre des caractères à l'intérieur IFSest important lors de l'expansion "$*". Depuis la bashpage de manuel:

"$*" is equivalent to "$1c$2c...", where c is the first character of the value of
the IFS variable.  If IFS is unset, the parameters are separated by spaces.  If
IFS is null, the parameters are joined without intervening separators.

Pour plus d'exemples de fractionnement de mots, veuillez consulter cette réponse - https://unix.stackexchange.com/a/118444/48083

Graeme
la source
1
Le premier caractère de $IFSest également utilisé, "$*"ce qui explique pourquoi l'ordre est important.
Stéphane Chazelas
2
Notez également que zshle caractère NUL est inclus dans sa valeur par défaut $IFS(les autres shells ne prennent pas en charge le maintien du caractère NUL dans leurs variables).
Stéphane Chazelas