2017-09-20 10 views
2

これはコロンで区切られた値をループして各値を するコードです。zshはパラメータ展開後にIFSで分割されません

f() 
{ 
    IFS=: 
    for arg in $1 
    do 
     echo arg: $arg 
    done 
} 

f foo:bar:baz 

これはほとんどのPOSIX準拠のシェルで正常に動作します。

$ dash foo.sh 
arg: foo 
arg: bar 
arg: baz 
$ bash foo.sh 
arg: foo 
arg: bar 
arg: baz 
$ ksh foo.sh 
arg: foo 
arg: bar 
arg: baz 
$ posh foo.sh 
arg: foo 
arg: bar 
arg: baz 
$ yash foo.sh 
arg: foo 
arg: bar 
arg: baz 

しかし、zshでは期待通りに動作しません。

$ zsh foo.sh 
arg: foo:bar:baz 

zshはPOSIXに違反していますか?

+0

はい、zshのがここ違反して故意に意図的です。つまり、文字列分割に頼っているのは、どのシェルでも良い習慣ではありません。つまり、bashでも、 'read -r -a args <<<" $ 1 "'などを使って読むことをお勧めします$ {args [@]} ";で配列の中に' for arg 'を挿入します。 do ... ... –

+1

これは、 'zsh'がPOSIX *が何をすべきかを行う場合です。POSIXは既存の動作を可能な限り維持することに負担を掛けていませんでした。最悪の解決法として、 'setopt SH_WORD_SPLIT'を使ってPOSIXの動作を復元することができます。 – chepner

答えて

2

はい。 Zshは独自の方法を選んだ。あなたが見てみることができ

$ zsh -y foo.sh 
arg: foo 
arg: bar 
arg: baz 

:あなたはzsh呼び出しに-yオプションを追加することで回避することができ、この特定のケースで “3.1: Why does $var where var="foo bar" not do what I expect?”

:ここ

はzshのよくある質問エントリです the zsh's faq特に第2章と第3章。 他のシェルを経験するほど、zshの落とし穴を見つけることができます。

1

Zshでは、提供された(s)フラグ(これは、IFSを使用)を使用して分割するのが通常はよりクリーンです。 あなたのデータのためのソリューションは次のようになります。

% f() { for e in ${(s.:.)1}; print $e } 
% f foo:bar:baz 
foo 
bar 
baz 

は 詳細や関連フラグのzshexpn(1) manページでPARAMETER EXPANSIONセクションを参照してください。

(私はあなたがコロン区切られた値を意味すると仮定します。)

関連する問題