bashのカットが失敗するのにzshが失敗するのはなぜですか?

bashのカットが失敗するのにzshが失敗するのはなぜですか?

タブで区切られたフィールドを持つファイルを作成します。

echo foo$'\t'bar$'\t'baz$'\n'foo$'\t'bar$'\t'baz > input

次のスクリプト名があります。zsh.sh

#!/usr/bin/env zsh
while read line; do
    <<<$line cut -f 2
done < "$1"

テストしてみましょう。

$ ./zsh.sh input
bar
bar

これは素晴らしい作品です。ただし、最初の行を変更して呼び出すとbash失敗します。

$ ./bash.sh input
foo bar baz
foo bar baz

これが失敗しbashて動作するのはなぜですかzsh

その他のトラブルシューティング

  • 代わりに、shebangで直接パスを使用すると、env同じ動作が発生します。
  • echoここで文字列の代わりにパイプを使用すると、<<<$line同じ動作が生成されます。つまりecho $line | cut -f 2
  • awk代わりに使用cut 働く両方のシェルに対応します。つまり<<<$line awk '{print $2}'

ベストアンサー1

これは、4.4より前のバージョンでは<<< $line引用符がない場合(ワイルドカードではありません)、単語分割が行われ、結果の単語が空白文字で連結されたためです(そして一時ファイルに入れて改行して次に設定しました)。標準入力)。bash$linecut

$ a=a,b,,c bash-4.3 -c 'IFS=","; sed -n l <<< $a'
a b  c$

tabデフォルトは次のとおりです$IFS

$ a=$'a\tb'  bash-4.3 -c 'sed -n l <<< $a'
a b$

解決策はbash変数を参照することです。

$ a=$'a\tb' bash -c 'sed -n l <<< "$a"'
a\tb$

これを行う唯一のシェルであることに注意してください。zsh<<<Byron Rakitzisの実装からインスピレーションを得たソースrc)、ksh93またこれを行わないmkshようにyashサポートします<<<

配列の場合、、、mkshおよびyashzshの最初の文字で連結され、スペースで連結されます。$IFSbashksh93

$ mksh -c 'a=(1 2); IFS=:; sed -n l <<< "${a[@]}"'
1:2$
$ yash -c 'a=(1 2); IFS=:; sed -n l <<< "${a[@]}"'
1:2$
$ ksh -c 'a=(1 2); IFS=:; sed -n l <<< "${a[@]}"'
1 2$
$ zsh -c 'a=(1 2); IFS=:; sed -n l <<< "${a[@]}"'
1:2$
$ bash -c 'a=(1 2); IFS=:; sed -n l <<< "${a[@]}"'
1 2$

空の場合はzsh/yashmksh(少なくともR52バージョン)の間に違いがあります。$IFS

$ mksh -c 'a=(1 2); IFS=; sed -n l <<< "${a[@]}"'
1 2$
$ zsh -c 'a=(1 2); IFS=; sed -n l <<< "${a[@]}"'
12$

使用時の動作はシェル全体でより一貫しています("${a[*]}"空の場合でもmkshエラーが発生する場合を除く$IFS)。

ただし、Bourneに似たすべてのシェル(および関連FAQ)echo $line | ...の一般的な分割+glob演算子です。zshecho

おすすめ記事