我想从遇到stdin
字符串分隔符开始读取MARKER=$'\0'"BRISH_MARKER"
。我试过:
❯ unset br ; print -rn -- hi${MARKER}world | { IFS= read -d "$MARKER" -r br ; cat -v } ; echo ; typeset -p br
这使:
BRISH_MARKERworld
typeset br=hi
因此read
仅使用给定分隔符的第一个字符\0
。我希望它使用整个字符串。我怎样才能实现这个目标?
我试图解决的问题是,我有一个进程不断地将数据流提供给 zsh 进程,并且需要使用分隔符将数据分解为不同的值。我最初只使用\0
,但这不允许我使用包含 的值\0
,所以我尝试使用当前的MARKER
.
答案1
Yesread -d
仅适用于单字符分隔符(在bash
和中ksh93
,它仅适用于单字符分隔符)字节分隔符)。
读取到定界符还意味着您需要一次读取一个字节(尤其是对于不可查找的输入,例如管道)以确保您不会读取过去的分隔符,这使得它效率低下。
我建议使用length:value
记录代替:
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"
}
(multibyte
在本地禁用那些以字节为单位的长度,并避免此处无用的字符编码/解码)。
那么作为一个例子:
$ (write-record $'é\0x'; write-record $'foo\0MARKER') | { read-record a && read-record b; printf "<%q>\n" "$a" "$b"; }
<é$'\0'x>
<foo$'\0'MARKER>