Mengapa ini "sambil membaca" bekerja di terminal, tetapi tidak dalam skrip shell?

8

Saya mengalami masalah menarik ini saat mengisi bilah WM saya dengan teks info, yang diterapkan dengan mengatur judul jendela root, yaitu xsetroot -name "clever words"

Untuk tujuan ini, mencetak keberuntungan bekerja dengan baik di terminal:

fortune -s | while read -r; do xsetroot -name "$REPLY"; done

Namun hal yang sama gagal ketika dijalankan dari skrip shell:

#!/bin/sh
cat /tmp/afile | while read; do echo "$REPLY"; done

Menghasilkan:

$ sh afilereader
afilereader: 2: baca: arg count

Tentu saja ini diatasi dengan menetapkan hasil keberuntungan kami ke suatu variabel, kemudian menggunakan xsetroot dengan variabel tersebut. Tapi saya masih ingin mengerti mengapa ini tidak berhasil dalam naskah.

Saya menyadari bahwa setiap perintah di kedua sisi pipeline dijalankan di dalam subshell itu sendiri, tetapi gagal untuk melihat bagaimana variabel lokal mereka dapat mempengaruhi loop saat membaca. Atau apakah variabel berada di luar cakupan bahkan di antara iterasi loop?

Apa yang saya lewatkan?

Update: The shI digunakan terkait dengan dasbor, yang dalam proses yang dibuat POSIX compliant. Menggunakan yang lebih terhormat bashmemecahkan ini.

membalikkan
sumber
1
Perilaku dash di sini tidak menunjukkan kekurangan kepatuhan POSIX. POSIX tidak mengharuskan readinvocable tanpa variabel: pubs.opengroup.org/onlinepubs/9699919799/utilities/read.html
dubiousjim

Jawaban:

10

Anda tampaknya menjalankan contoh pertama bash, dan yang kedua dalam apa pun yang ditunjukkan oleh /bin/sh, yang merupakan shell POSIX yang membutuhkan argumen untuk dilewati menentukan variabel yang Anda ingin masukkan input. Mengubah shebang ke #!/bin/bashharus memperbaiki ini.

Chris Down
sumber
Pengamatan yang baik @ Chris! Itu bekerja. Pikir saya akan membaca sedikit tentang perbedaan antara shdan bash.
balikkan
Memang tidak normal! Saya dapat menghubungkan kembali /bin/shke bash, tetapi saya pikir saya hanya akan menggunakan bash langsung dari sekarang, untuk menghindari ambiguitas. Terima kasih :)
invert
Kerang interaktif sering berbeda dari skrip shell dalam buffering dari output mereka. Membaca dari pipa antar-proses dapat menghasilkan segala macam perilaku pengaturan waktu yang aneh jika perintah yang menghasilkan keluaran mendukung penulisan ketika dijalankan secara non-interaktif.
JesseM
5

Dalam sintaksis sh, Anda perlu

IFS= read -r REPLY

Beberapa shell seperti ksh, bash dan zsh memungkinkan readuntuk dipanggil tanpa nama variabel tetapi perilaku berbeda di antara mereka. Lihat misalnya output dari

printf 'te\ st\\\na ' | "$shell" -c 'read; printf "%s\n" "<$REPLY>"'

berbeda pada semua bash, zsh, pdksh dan ksh93

Stéphane Chazelas
sumber
Masuk akal mengapa shell yang saya gunakan tidak tahu nama variabelnya, terima kasih @Stephane.
terbalik