エグゼクティブサマリー
プロセス置換を行うときにシェルが NUL バイトをスキップするのは標準的な動作ですか?
たとえば、
printf '\0abc' | read value && echo $value
お譲り致しabc
ます。printf
出力の 16 進ダンプで明らかに出力されていることが示されていても、NUL 値はスキップされます。
私の最初の考えは「単語分割」でした。ただし、実際のプロセス代替を使用する場合は、
value=$(printf '\0abc')
結果は類似しており、=
単語分割は実行されません。
長い話
この質問に対する適切な答えを探しているときに、プロセス置換から変数に値を読み取るときに、私がかなり慣れている少なくとも 3 つのシェル実装 (ash、zsh、および bash) が NUL 文字を無視することに気付きました。
これが発生するパイプラインの正確なポイントは異なるようですが、最初から存在しなかったかのように、一貫して NUL バイトがドロップされます。
いくつかの実装を確認しましたが、これは正常な動作のようです。
ash
inputをスキップし'\0'
ますが、これが純粋な偶然なのか意図した動作なのかは、コードからは明らかではありません。
if (lastc != '\0') {
[...]
}
bash
ソース コードには、プロセス置換で NUL 値をスキップしたことを示す明示的な#ifdef
警告が含まれています。
#if 0
internal_warning ("read_comsub: ignored null byte in input");
#endif
zsh
さんの行動についてはよくわかりません。(内部関数'\0'
で定義されているように) メタ文字として認識し、特殊なサロゲート文字を先頭に追加し、入力文字にビット #5 を設定して、基本的にメタ文字を解除します。これにより、makeもスペースになります) 。imeta()
Meta
'\0'
' '
if (imeta(c)) {
*ptr++ = Meta;
c ^= 32;
cnt++;
}
value
上記のprintf
コマンドにメタ文字が含まれているという証拠がないため、これは後で削除されるようです。私はzsh
の内部構造に慣れていないので、これを大いに参考にしてください。また、副作用のないステートメントにも注意してください。
zsh
に NUL (メタエスケープ) を含めることもできることに注意してください(たとえば、なしIFS
で単語を分割することが可能になります)。したがって、 との値に応じて異なる結果が得られるはずです(フィールド分割を行います)。find -print0
xargs -0
printf '\0abc' | read value
value=$(printf '\0abc')
IFS
read