web-dev-qa-db-ja.com

zshで一度に1ワードずつ文字列を反復処理する方法

次のコードを変更して、zshで実行したときに$thingsとそれらを1つずつ繰り返しますか?

things="one two"

for one_thing in $things; do
    echo $one_thing
done

出力を次のようにします。

one 
two

しかし、上に書いたように、それは出力します:

one two

(bashで上記のコードを実行したときに得られる動作を探しています)

22
Rob Bednark

Bourne Shellと互換性のある動作を確認するには、オプション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

ただし、Word分割の生成には配列を使用することをお勧めします。

things=(one two)

for one_thing in $things; do
    echo $one_thing
done

以下を参照することもできます。

.1:var = "foo bar"の$ varが期待どおりに動作しないのはなぜですか?

42
devnull

z変数展開フラグを使用して、変数でWord分割を実行できます。

things="one two"

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

これと他の変数フラグの詳細については、man zshexpnの「Parameter Expansion Flags」を参照してください。

7
Kevin

Bashの内部フィールドセパレーター(IFS)は\ x20(スペース)であると想定できます。これにより、次のことが可能になります。

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

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

これを念頭に置いて、IFSを操作するだけでさまざまな方法でこれを実装できます。複数行の文字列でも。

3
Atttacat

Bourneシェル(sh、bash、zshなど)の間でも移植可能な別の方法:

things="one two"

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

または、$thingsを変数として定義する必要がない場合:

for one_thing in one two; do
    echo $one_thing
done

for x in y zを使用すると、単語のリストy, zをループするようシェルに指示されます。

最初の例では、 コマンド置換 を使用して、文字列"one two"を単語のリストone two(引用符なし)に変換します。

2番目の例は、echoなしの同じものです。

うまく理解できない例があります:

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

引用符に注意してください。これは単に印刷されます

one two

引用符は、リストにone twoという単一の項目があることを意味するためです。

1
bgdnlp