タブで区切られたフィールドを持つファイルを作成します。
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
$line
cut
$ 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
およびyash
はzsh
の最初の文字で連結され、スペースで連結されます。$IFS
bash
ksh93
$ 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
/yash
とmksh
(少なくとも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演算子です。zsh
echo