web-dev-qa-db-ja.com

Bash読み取り:カンマ区切りリストの読み取り、最後の要素が欠落しています

以下のコマンドの出力は私には奇妙です。なぜ要素5が返されないのですか?

_$ echo '0,1,2,3,4,5' | while read -d, i; do echo $i; done
0
1
2
3
4
_

「5」も返されると思います。 GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)を実行しています。コンマの追加は機能しますが、入力データにコンマがありません。何か不足していますか?

8
Karlo

readでは、_-d_を使用して入力行を終了します(つまり、入力行を分離しません)。最後の「行」にはターミネータが含まれていないため、readはEOFでfalseを返し、ループは終了します(最終値が読み取られた場合でも)。

_echo '0,1,2,3,4,5' | { while read -d, i; do echo "$i"; done; echo "last value=$i"; }
_

(_-d_を使用しても、readは_$IFS_も使用し、readarrayなどの他のメソッドを使用して表示される最終値の末尾の_\n_を含む空白を吸収します)

Bash FAQは、これと、同様のさまざまなケースを処理する方法について説明しています。

12
mr.spuratic

他の回答が述べるように、-dは、フィールド区切り文字ではなく、行末文字です。できるよ

IFS=, read -a fields <<< "1,2,3,4,5"
for i in "${fields[@]}"; do echo "$i"; done
8
Graham Breed

男から:

-d delim

Delimの最初の文字は、改行ではなく入力行を終了するために使用されます。

エレメント5には区切り文字(コンマ)がないため、読み取られません。

5
msp9011

あなたが見ているのは と同じ振る舞いです(そして同じ理由で)この「while」ループが最後の行を認識しないのはなぜですか?

その場合と同様に、次のように、ループ終了条件にテストを追加することで動作を変更できます。

while read -d, i || [[ -n $i ]]; do ...

例.

$ echo '0,1,2,3,4,5' | while read -d, i || [[ -n $i ]]; do echo $i; done
0
1
2
3
4
5
3
steeldriver