web-dev-qa-db-fra.com

Comment parcourir une chaîne mot par mot dans zsh

Comment puis-je modifier le code suivant de sorte que lorsqu'il est exécuté dans zsh, il développe $things et l'itère l'un après l'autre?

things="one two"

for one_thing in $things; do
    echo $one_thing
done

Je veux que la sortie soit:

one 
two

Mais comme écrit ci-dessus, il génère:

one two

(Je recherche le comportement que vous obtenez lorsque vous exécutez le code ci-dessus dans bash)

20
Rob Bednark

Pour voir le comportement compatible avec Bourne Shell, vous devez définir l'option SH_Word_SPLIT:

setopt shwordsplit      # this can be unset by saying: unsetopt shwordsplit
things="one two"

for one_thing in $things; do
    echo $one_thing
done

produirait:

one
two

Cependant, il est recommandé d’utiliser un tableau pour produire le fractionnement de Word, par exemple, 

things=(one two)

for one_thing in $things; do
    echo $one_thing
done

Vous voudrez peut-être aussi vous référer à:

3.1: Pourquoi $ var où var = "foo bar" ne fait-il pas ce que j'attends?

38
devnull

Vous pouvez utiliser l'indicateur d'expansion de variable z pour effectuer le fractionnement de Word sur une variable.

things="one two"

for one_thing in ${(z)things}; do
    echo $one_thing
done

En savoir plus sur cela et sur les autres indicateurs de variable dans man zshexpn, sous "Indicateurs d'expansion de paramètres"

5
Kevin

Vous pouvez supposer que le séparateur de champ interne (IFS) sur bash est\x20 (espace). Cela rend le travail suivant:

#IFS=$'\x20'
#things=(one two) #array
things="one two"  #string version

for thing in ${things[@]}
do
   echo $thing
done

En gardant cela à l'esprit, vous pouvez implémenter cela de différentes façons en manipulant simplement l'IFS; même sur des chaînes multi-lignes.

2
Atttacat

Une autre façon, qui est également portable entre les obus Bourne (sh, bash, zsh, etc.):

things="one two"

for one_thing in $(echo $things); do
    echo $one_thing
done

Ou, si vous n'avez pas besoin de $things défini en tant que variable:

for one_thing in one two; do
    echo $one_thing
done

Utiliser for x in y z donnera instruction au shell de parcourir une liste de mots, y, z.

Le premier exemple utilise commande substitution pour transformer la chaîne "one two" en une liste de mots, one two (sans guillemets).

Le deuxième exemple est la même chose sans echo.

Voici un exemple qui ne fonctionne pas, pour mieux le comprendre: 

for one_thing in "one two"; do
    echo $one_thing
done

Remarquez les citations. Cela va simplement imprimer

one two

parce que les guillemets signifient que la liste ne contient qu'un seul élément, one two.

1
bgdnlp