Как перебирать строку по одному слову за раз в zsh

Как мне изменить следующий код, чтобы при запуске в zsh он расширял $things и повторял их по одному за раз?

things="one two"

for one_thing in $things; do
    echo $one_thing
done

Я хочу, чтобы выход был:

one 
two

Но, как написано выше, он выводит:

one two

(Я ищу поведение, которое вы получаете при запуске вышеуказанного кода в bash)

Ответ 1

Чтобы увидеть поведение, совместимое с оболочкой Bourne, вам нужно установить опцию 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

создаст:

one
two

Однако он рекомендовал использовать массив для создания разбиения слов, например

things=(one two)

for one_thing in $things; do
    echo $one_thing
done

Вы также можете обратиться к:

3.1: Почему $var, где var = "foo bar" не выполняет то, что я ожидаю?

Ответ 2

Вы можете использовать флаг расширения z для разделения слов на переменной

things="one two"

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

Подробнее об этом и других переменных флагах в man zshexpn читайте в разделе "Флаги расширения параметров".

Ответ 3

Вы можете считать, что внутренний разделитель полей (IFS) на bash равен \x20 (пробел). Это делает следующую работу:

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

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

С учетом этого вы можете реализовать это разными способами, просто манипулируя IFS; даже в многострочных строках.