web-dev-qa-db-fra.com

Utiliser "while read ..." dans un script linux

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….

34
linuxgringo

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.

41
Florian Diesch

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 whilen'apporte vraiment rien. La variable intégrée readlit 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 aet bprennent respectivement les valeurs 1 et 2, tandis que cprend 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 readest é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 readbuiltin , 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 : readname __: 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 , readva toujours (essayer de) lire une ligne entière - et que readest destiné à être utilisable à la fois avec et sans boucle .

24
Eliah Kagan