Comment peut-on correctement parcourir les lignes de bash soit dans une variable, soit à partir du résultat d'une commande? Définir simplement la variable IFS sur une nouvelle ligne fonctionne pour la sortie d'une commande, mais pas pour le traitement d'une variable contenant de nouvelles lignes.
Par exemple
#!/bin/bash
list="One\ntwo\nthree\nfour"
#Print the list with echo
echo -e "echo: \n$list"
#Set the field separator to new line
IFS=$'\n'
#Try to iterate over each line
echo "For loop:"
for item in $list
do
echo "Item: $item"
done
#Output the variable to a file
echo -e $list > list.txt
#Try to iterate over each line from the cat command
echo "For loop over command output:"
for item in `cat list.txt`
do
echo "Item: $item"
done
Cela donne la sortie:
echo:
One
two
three
four
For loop:
Item: One\ntwo\nthree\nfour
For loop over command output:
Item: One
Item: two
Item: three
Item: four
Comme vous pouvez le constater, l'écho de la variable ou une itération sur la cat
commande imprime correctement chacune des lignes. Cependant, la première boucle for imprime tous les éléments sur une seule ligne. Des idées?
Réponses:
Avec bash, si vous souhaitez incorporer des nouvelles lignes dans une chaîne, entourez-la de la manière suivante
$''
:Et si vous avez déjà une telle chaîne dans une variable, vous pouvez la lire ligne par ligne avec:
la source
done <<< "$list"
est crucialedone <<< "$list"
est cruciale est que cela passera "$ list" comme entrée pourread
$list
est très cruciale.echo "$list" | while ...
pourrait paraître plus clair que... done <<< "$line"
Vous pouvez utiliser
while
+read
:Btw. l'
-e
option toecho
est non standard. Utilisezprintf
plutôt si vous voulez la portabilité.la source
<<<
version suggérée par glenn jackman ne fonctionne avec affectation variable.while
pièce. La<<<
version ne le fait pas (du moins dans les nouvelles versions de bash).la source
IFS=$'\n'
pour le même effet.Voici une façon amusante de faire votre boucle:
Un peu plus sensible / lisible serait:
Mais c'est trop complexe, vous n'avez besoin que d'un espace:
Votre
$line
variable ne contient pas de nouvelles lignes. Il contient des instances de\
suivi den
. Vous pouvez voir cela clairement avec:La substitution consiste à remplacer celles-ci par des espaces, ce qui est suffisant pour que cela fonctionne dans les boucles:
Démo:
la source
cr
peut être utilisée$'\n'
.Vous pouvez également d'abord convertir la variable en un tableau, puis parcourir celui-ci.
Ce n'est utile que si vous ne voulez pas jouer avec le
IFS
et que vous avez également des problèmes avec laread
commande, comme cela peut arriver, si vous appelez un autre script dans la boucle, ce script peut vider votre tampon de lecture avant de revenir, comme cela m'est arrivé .la source