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?
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.
-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
.
É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é.
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)