Shell

zsh:從標準輸入讀取直到字元串分隔符

  • September 1, 2020

我想讀取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 程序,並且需要使用分隔符將數據分解為不同的值。我最初使用 just \0,但這不允許我使用包含 的值\0,所以我嘗試使用目前的MARKER.

Yesread -d僅適用於單字元分隔符(在bashand中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>

引用自:https://unix.stackexchange.com/questions/607266