空の文字列を引数として使用する場合、「read」シェルコマンドの「-d」オプションは何をしますか?

空の文字列を引数として使用する場合、「read」シェルコマンドの「-d」オプションは何をしますか?

私が読んだときこの回答、作成者はこのコマンドを使用して、区切り文字の結果を変数に入れます。

read -r -d '' VAR <<'EOF'
abc'asdf"
$(dont-execute-this)
foo"bar"''
EOF

このオプションについて少し混乱しています-d。このコマンドのヘルプテキストからread

-d delim
continue until the first character of DELIM is read, rather than newline

したがって、空の文字列を渡すことは、-d次のことを意味します。最初の空の文字列まで読む。どういう意味ですか?著者は、-d ''NUL文字列を区切り文字として使用する方法に対する回答の下にコメントしました。これは本当ですか(空の文字列はNUL文字列を意味します)?-d '\0'などを使用しないのはなぜですか-d '\x0'

ベストアンサー1

ほとんどの場合、これは正確に言うことを意味します。たとえば、次のようになります。

$読み取り-d。変数エコー。 "読む: '$var'"
金持ち。
読む: 'foo'

読み取りはすぐに終了し、.そこでEnterキーを押しませんでした。

しかし、read -d ''状況は少し珍しいです。オンラインリファレンスマニュアルによると:

-d delim
delimの最初の文字は、改行文字ではなく入力行を終了するために使用されます。delimが空の文字列の場合、readはNUL文字を読み取ると行を終了します。

\0表現のNULバイトprintfなので、例えば次のようになります。

$ printf 'foo\0bar\0' | while read -d '' var; do echo "read: '$var'"; done
read: 'foo'
read: 'bar'

あなたの例では、read -d ''改行文字が区切り文字になるのを防ぐために、一度に1行を読むのではなく、一度に複数行の文字列を読み取ることができます。


一部の以前のバージョンのドキュメントでは、この動作について明示的に言及していないようです-d ''。この動作は、もともとBashがCで文字列を保存する方法(末尾のNULバイトを含む)と偶然一致している可能性があります。文字列はfooとして保存されfoo\0、空の文字列はとして保存されます\0。したがって、実装時に注意を払わずにメモリの最初のバイトのみを選択した場合は、\0NULを空の文字列の最初のバイトとして扱います。

質問をもっとよく読んで、次のように言及しました。

著者は、答えの下でこれが次のことを-d ''使用することを意味すると述べました。NUL文字列区切り記号で。

これは完全に正確ではありません。空の文字列(POSIXという用語)は、内容が含まれていない長さがゼロの文字列である空の文字列を意味します。これは以下に関連しています。ヌルバイト、これはバイナリ値が0(*)のシングルバイトです。空の文字列を区切り文字として使用すると、ほぼすべての場所で見つけることができます。シェルではこれは可能ではないと思います。しかし、例えばPerlでは、次のように文字列を分割することが可能です。

$ perl -le 'print join ":", split "", "foobar";'
f:o:o:b:a:r

read -d ''NULの使用バイト区切り記号で。

(*そして特徴 0、間違いなく。 )

-d '\0'などを使用しないのはなぜですか-d '\x0'

良い質問ですね。 Stéphaneが述べたように、最初にksh93はそれをサポートしてread -dおらread -d ''ず、バックスラッシュエスケープをサポートするように変更すると元のバージョンと互換性がありません。しかし、あなたはできる必要に応じて使用できます(同様のタブなどread -d $'\0')。 Bashは文字列でNULバイトをサポートしていないため、$'\t'後でBashと同じです。-d ''Zshは、-d ''しかしと-d $'\0'

おすすめ記事