zsh: Membaca dari stdin hingga pemisah string
Saya ingin membaca stdinsampai pemisah string MARKER=$'\0'"BRISH_MARKER" ditemukan. Saya mencoba:
❯ unset br ; print -rn -- hi${MARKER}world | { IFS= read -d "$MARKER" -r br ; cat -v } ; echo ; typeset -p br
Pemberian yang mana:
BRISH_MARKERworld
typeset br=hi
Jadi, readhanya menggunakan karakter pertama dari pembatas yang diberikan \0,. Saya ingin menggunakan seluruh string. Bagaimana saya bisa mencapai ini?
Masalah yang saya coba selesaikan adalah saya memiliki proses yang terus menerus memasukkan aliran data ke proses zsh, dan data perlu dipecah menjadi nilai yang berbeda menggunakan pembatas. Saya awalnya menggunakan just \0, tetapi itu tidak memungkinkan saya untuk menggunakan nilai yang mengandung \0, jadi saya mencoba menggunakan arus MARKER.
Jawaban
Ya read -dhanya bekerja dengan pembatas satu karakter (dalam bashdan ksh93, hanya bekerja dengan pembatas byte tunggal ).
Membaca hingga pembatas juga berarti Anda perlu membaca satu byte pada satu waktu (terutama dengan input yang tidak dapat dicari seperti pipa) untuk memastikan Anda tidak membaca melewati pembatas, yang membuatnya tidak efisien.
Saya sarankan menggunakan length:valuecatatan sebagai gantinya:
write-record() {
set -o localoptions +o multibyte
print -rn -- "$#1:$1"
}
read-record() {
set -o localoptions +o multibyte
local len
# note that in current versions of zsh, read -k0 (for empty records)
# returns a non-zero exit status.
eval "$1=" IFS= read -rd: len || return ((len == 0)) || read -u0 -k "$len" "$1"
}
(menonaktifkan multibytesecara lokal untuk bekerja dengan panjang dalam byte dan menghindari pengkodean / dekode karakter yang tidak berguna di sini).
Kemudian sebagai contoh:
$ (write-record $'é\0x'; write-record $'foo\0MARKER') | { read-record a && read-record b; printf "<%q>\n" "$a" "$b"; }
<é$'\0'x> <foo$'\0'MARKER>