web-dev-qa-db-fra.com

Que fait IFS = dans cette boucle bash: `fichier cat | tandis que IFS = lire la ligne -r; faire ... fait`

J'apprends bash et j'ai vu cette construction:

cat file | while IFS= read -r line;
do
    ...
done

Quelqu'un peut-il expliquer ce que IFS= Est-ce que? Je sais que c'est un séparateur de champ d'entrée, mais pourquoi est-il réglé sur rien?

23
bodacydo

IFS fait beaucoup de choses mais vous posez des questions sur cette boucle particulière.

L'effet dans cette boucle est de conserver les espaces blancs de début et de fin dans line. Pour illustrer, observez d'abord avec IFS défini sur rien:

$ echo " this   is a test " | while IFS= read -r line; do echo "=$line=" ; done
= this   is a test =

La variable line contient tout l'espace blanc qu'elle a reçu sur son stdin. Maintenant, considérez la même instruction avec l'IFS par défaut:

$ echo " this   is a test " | while read -r line; do echo "=$line=" ; done
=this   is a test=

Dans cette version, l'espace blanc interne à la ligne est toujours conservé. Mais, l'espace blanc avant et arrière ont été supprimés.

Que fait -r Dans read -r?

L'option -r Empêche read de traiter la barre oblique inverse comme un caractère spécial.

Pour illustrer, nous utilisons deux commandes echo qui fournissent deux lignes à la boucle while. Observez ce qui se passe avec -r:

$ { echo 'this \\ line is \' ; echo 'continued'; } | while IFS= read -r line; do echo "=$line=" ; done
=this \\ line is \=
=continued=

Maintenant, observez ce qui se passe sans -r:

$ { echo 'this \\ line is \' ; echo 'continued'; } | while IFS= read line; do echo "=$line=" ; done
=this \ line is continued=

Sans -r, Deux changements se sont produits. Tout d'abord, la double barre oblique inverse a été convertie en une seule barre oblique inverse. Deuxièmement, la barre oblique inversée à la fin de la première ligne a été interprétée comme un caractère de continuation de ligne et les deux lignes ont été fusionnées en une seule.

En somme, si vous voulez que les barres obliques inverses dans l'entrée aient une signification spéciale, n'utilisez pas -r. Si vous souhaitez que les barres obliques inverses dans l'entrée soient considérées comme des caractères simples, utilisez -r.

Plusieurs lignes d'entrée

Étant donné que read prend l'entrée une ligne à la fois, IFS se comporte affecte chaque ligne d'entrée de plusieurs lignes de la même manière qu'il affecte l'entrée d'une seule ligne. -r Se comporte de manière similaire à l'exception que, sans -r, Plusieurs lignes peuvent être combinées en une seule ligne à l'aide de la barre oblique inverse de fin, comme illustré ci-dessus.

Le comportement avec l'entrée de plusieurs lignes, cependant, peut être radicalement changé en utilisant l'indicateur -d De read. -d Modifie le caractère de délimitation que read utilise pour marquer la fin d'une ligne d'entrée. Par exemple, nous pouvons terminer les lignes avec un caractère de tabulation:

$ echo $'line one \n line\t two \n line three\t ends here'
line one 
 line    two 
 line three      ends here
$ echo $'line one \n line\t two \n line three\t ends here' | while IFS= read -r -d$'\t' line; do echo "=$line=" ; done
=line one 
 line=
= two 
 line three=

Ici, la construction $'...' A été utilisée pour saisir des caractères spéciaux comme la nouvelle ligne, \n Et l'onglet, \t. Notez qu'avec -d$'\t', read divise son entrée en "lignes" en fonction des tabulations. Tout ce qui se trouve après l'onglet final est ignoré.

Comment gérer les noms de fichiers les plus difficiles

L'utilisation la plus importante des fonctionnalités décrites ci-dessus consiste à traiter les noms de fichiers difficiles. Étant donné que le seul caractère qui ne peut pas apparaître dans chemin/noms de fichiers est le caractère nul, le caractère nul peut être utilisé pour séparer une liste de noms de fichiers. Par exemple:

while IFS= read -r -d $'\0' file
do
    # do something to each file
done < <(find ~/music -type f -print0)
50
John1024