zsh: 標準入力から文字列区切り文字まで読み込みます。

zsh: 標準入力から文字列区切り文字まで読み込みます。

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

はいread -d単一文字区切り文字でのみ機能します。 (単一文字の区切り文字でのみ機能します。bashksh93バイト分離記号)。

区切り文字を読み取るとは、読み取らないようにするために一度に1バイトずつ読み取る必要があることを意味します(特にパイプなどのナビゲートできない入力の場合)。過去区切り記号のため非効率的です。

代わりにロギングを使用することをお勧めします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>

関連情報