Bash Read: Membaca daftar yang dipisahkan koma, elemen terakhir tidak terjawab


8

Output dari perintah di bawah ini aneh bagi saya. Mengapa itu tidak memberi saya kembali elemen 5?

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

Saya harapkan '5' akan dikembalikan juga. Lari GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu). Menambahkan koma berfungsi, tetapi data input saya tidak memiliki koma. Apakah saya melewatkan sesuatu?

Jawaban:


12

Dengan read, -ddigunakan untuk mengakhiri jalur input (yaitu untuk tidak memisahkan jalur input). "Baris" terakhir Anda tidak mengandung terminator, jadi readmengembalikan false pada EOF dan loop keluar (meskipun nilai akhir dibaca).

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

(Bahkan dengan -d, readjuga menggunakan $IFS, menyerap spasi termasuk trailing \npada nilai akhir yang akan muncul menggunakan metode lain seperti readarray)

Bash FAQ membahas ini, dan bagaimana menangani berbagai kasus serupa:


8
Saya kira orang bisa melakukan read -d, i || [[ -n $i ]]a la Apa while read -r line || [[ -n $line ]]artinya?
steeldriver

8

Sebagai jawaban lainnya menyatakan, -dadalah karakter end-of-line, bukan pemisah bidang. Anda dapat melakukan

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

5

Dari manusia:

-d delim

Karakter pertama delim digunakan untuk mengakhiri jalur input, bukan baris baru.

Elemen 5 Anda tidak memiliki pembatas (koma), sehingga tidak akan dibaca.


Jadi perbaikan terbaik adalah meletakkan koma lain setelah input?
Karlo

3
The memperbaiki terbaik mungkin untuk mengolah data dengan sesuatu yang lain dari shell . Karena para penjawab di sini telah menjawab pertanyaan saat ini, Anda dapat mempertimbangkan pertanyaan terpisah yang menunjukkan tujuan Anda yang lebih besar.
Jeff Schaller

3

Apa yang Anda lihat adalah perilaku yang sama (dan untuk alasan yang sama) seperti Mengapa loop 'sementara' ini tidak mengenali baris terakhir?

Seperti dalam kasus itu, Anda dapat memodifikasi perilaku dengan menambahkan tes tambahan ke kondisi terminasi loop, sebagai berikut

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

Ex.

$ echo '0,1,2,3,4,5' | while read -d, i || [[ -n $i ]]; do echo $i; done
0
1
2
3
4
5
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.