Quelqu'un pourrait-il s'il vous plaît expliquer comment le code suivant fonctionne?
echo '1 2 3 4 5 6' | while read a b c
do
echo $c $b $a
done
Plus précisément, j'aimerais savoir pourquoi le résultat de cette boucle est 3 4 5 6 2 1
, au lieu de 3 2 1
et 6 5 4
sur deux lignes distinctes? Je n'arrive pas à penser à cela….
read
lit une ligne entière à partir de l'entrée standard, la divise en champs et attribue ces champs aux variables données. S'il y a plus de pièces que de variables, les pièces restantes sont affectées à la dernière variable.
Dans votre cas, $a
est attribué à 1
, $b
est attribué à 2
et $c
au 3 4 5 6
restant.
La réécriture de la boucle de cette façon révèle ce qui se passe:
echo '1 2 3 4 5 6' | while read a b c
do
echo '(iteration beginning)' a="$a" b="$b" c="$c" '(iteration ending)'
done
Cela donne, à sa sortie:
(iteration beginning) a=1 b=2 c=3 4 5 6 (iteration ending)
Notez tout d’abord que seule une commande echo est exécutée. S'il était exécuté plus d'une fois, vous verriez entre autres les chaînes (iteration beginning)
et (iteration ending)
imprimées plus d'une fois.
Cela revient à dire qu'avoir ici une boucle while
n'apporte vraiment rien. La variable intégrée read
lit du texte séparé par des espaces 1 dans chaque variable spécifiée. Une entrée supplémentaire est ajoutée à la fin de la dernière variable spécifiée. 2 Ainsi, les variables a
et b
prennent respectivement les valeurs 1
et 2
, tandis que c
prend la valeur 3 4 5 6
.
Lorsque la condition de boucle (while read a b c
) est évaluée pour la deuxième fois, il n’ya plus d’entrée disponible dans le tube (nous lui avons simplement acheminé une seule ligne de texte). La commande read
est évaluée à false au lieu de true et la boucle s'arrête (avant d'exécuter le corps une seconde fois).
1 : Pour être technique et spécifique, le read
builtin , lorsque les noms de variables sont passés en tant qu'arguments, lit les entrées, en le divisant en "mots" séparés quand il rencontre espaces blancs IFS (voir aussi cette question et cet article ).
2 : read
name __: le fait de brouiller tous les champs supplémentaires d'entrée dans la dernière variable spécifiée n'est pas intuitif pour beaucoup de scripteurs, au début. Il devient plus facile de comprendre quand on considère que, comme le dit la réponse de Florian Diesch , read
va toujours (essayer de) lire une ligne entière - et que read
est destiné à être utilisable à la fois avec et sans boucle .