Itération sur une chaîne de plusieurs lignes stockée dans une variable

17

J'ai lu qu'il est mauvais d'écrire des choses comme for line in $(command), la bonne façon semble être à la place:

command | while IFS= read -r line; do echo $line; done

Cela fonctionne très bien. Mais que se passe-t-il si ce que je veux répéter est le contenu d'une variable , pas le résultat direct d'une commande?

Par exemple, imaginez que vous créez le fichier suivant quickfox:

The quick brown
foxjumps\ over -
the
lazy ,
dog.

Je voudrais pouvoir faire quelque chose comme ça:

# This is just for the example,
# I could of course stream the contents to `read`
variable=$(cat quickfox);
while IFS= read -r line < $variable; do echo $line; done; # this is incorrect
Sheljohn
la source

Réponses:

19

Dans les shells modernes comme bash et zsh, vous avez un redirecteur `<<< 'très utile qui accepte une chaîne en entrée. Donc tu ferais

while IFS= read -r line ; do echo $line; done <<< "$variable"

Sinon, vous pouvez toujours faire

echo "$variable" | while IFS= read -r line ; do echo $line; done
lgeorget
la source
Désolé, j'aurais dû penser à faire écho au contenu bien sûr. Mais merci pour la réponse rapide quand même!
Sheljohn
1
vous devez faire un guillemet double $variablelorsque vous l'utilisez, sinon la whileboucle n'obtiendra qu'une seule ligne d'entrée. Voir, par exemple, la différence de sortie entre echo $variablevs echo "$variable"ou cat <<< $variablevs cat <<< "$variable".
cas
@cas En fait, cela dépend de ce qui se trouve dans $ variable. Dans le cas présenté par l'OP ("variable = $ (cat quickfox)") cela fonctionne sans les guillemets supplémentaires. Mais pour le cas général, vous avez raison. Je modifie ma réponse. Merci.
lgeorget
La variable=$(cat quickfox)question du PO lui-même fournit un exemple de ce dont je parlais. L'utilisation de ces $variableguillemets doubles inclut les sauts de ligne, sans les traduire par des espaces par le shell. Si vous lisez et traitez ligne par ligne, cela fait une énorme différence - avec la première, vous avez plusieurs lignes d'entrée, avec la dernière, vous n'avez qu'une seule ligne d'entrée. Les données d'entrée sont superficiellement similaires mais, dans la pratique, complètement différentes dans ces deux cas.
cas
par exemple: avec ces données d'entrée, cat <<< "$variable" | wc -lrenvoie 5. cat <<< $variable | wc -lrenvoie 1. Si vous voulez / devez conserver des espaces (y compris les sauts de ligne, les tabulations, les espaces simples ou multiples) dans une variable, vous DEVEZ double-citer la variable lorsque vous l'utilisez, sinon ils seront tous transformés en un seul espace entre chaque "mot".
cas