web-dev-qa-db-ja.com

$ '\ 0'または$ '\ x0'が空の文字列であるのはなぜですか?ヌル文字である必要がありますね。

bash$'string'拡張を許可します。私のman bashは言う:

$'string'の形式の単語は特別に扱われます。 Wordはstringに展開され、ANSIC標準で指定されているように円記号でエスケープされた文字が置き換えられます。バックスラッシュエスケープシーケンスが存在する場合は、次のようにデコードされます。
\aアラート(ベル)
\bバックスペース
\e
\Eエスケープ文字
\fフォームフィード
\n改行
\rキャリッジリターン
\t水平タブ
\v垂直タブ
\バックスラッシュ
\'一重引用符
\"二重引用符
\nnn値が8進値nnn(1〜3桁)の8ビット文字)
\xHH値が16進値である8ビット文字HH(1つまたは2つの16進数数字)
\cxコントロール-x文字

展開された結果は、ドル記号が存在しなかったかのように一重引用符で囲まれます。

しかし、なぜ bash$'\0'$'\x0'をヌル文字に変換しないのですか?
文書化されていますか?理由はありますか? (それは機能ですか、制限ですか、それともバグですか?)

$ hexdump -c <<< _$'\0'$'\x1\x2\x3\x4_'
0000000   _ 001 002 003 004   _  \n
0000007

echoは期待される結果をもたらします:

> hexdump -c < <( echo -e '_\x0\x1\x2\x3_' )
0000000   _  \0 001 002 003   _  \n
0000007

私のbashバージョン

$ bash --version | head -n 1
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

echo $'foo\0bar'echo -e 'foo\0bar'として動作しないのはなぜですか?

21
olibre

それは制限です。 bashは、文字列値に内部NULバイトを含めることを許可しません。

Posix(およびC)文字列に内部NULを含めることはできません。たとえば、文字列の Posix定義 (強調を追加)を参照してください。

3.92文字列

文字の連続シーケンス終了そして最初のヌルバイトを含みます。

同様に、標準Cは、文字列のNUL文字についてかなり明示的です。

§5.2.1p2…ヌル文字と呼ばれる、すべてのビットが0に設定されたバイトは、基本実行文字セットに存在する必要があります。 terminate文字列に使用されます。

Posixは、ファイル名(XBD 3.170)または環境変数(XBD8.1「...はヌルバイトで終わると見なされます」でのNUL(および/)の使用を明示的に禁止しています。

このコンテキストでは、bashを含むシェルコマンド言語は、単一のNULで終了する非NUL文字のシーケンスとして、文字列の同じ定義を使用する傾向があります。

もちろん、bashパイプを介してNULを自由に渡すことができ、NULバイトを出力するプログラムの出力にシェル変数を割り当てることを妨げるものは何もありません。ただし、Posixによると、結果は「指定されていません」(XSH 2.6.3「出力にnullバイトが含まれている場合、動作は指定されていません。」)。 bashでは、bashのCエスケープ構文($'\0')を使用して文字列にNULを挿入しない限り、NULは削除されます。挿入すると、NULは値を終了します。

実際には、ユーティリティのstdinにNULを挿入しようとする次の2つの方法の違いを考慮してください。

$ # Prefer printf to echo -n
$ printf $'foo\0bar' | wc -c
3
$ printf 'foo\0bar' | wc -c
7
$ # Bash extension which is better for strings which might contain %
$ printf %b 'foo\0bar' | wc -c
7
24
rici

しかし、bashが$'\0'$'\x0'をヌル文字に変換しないのはなぜですか?

ヌル文字は文字列を終了させるためです。

$ echo $'hey\0you'
hey
5
devnull

これはヌル文字ですが、それが何を意味するかによって異なります。

ヌル文字は空の文字列を表します。これは、展開すると取得される文字列です。これは特殊なケースであり、ドキュメントに含まれていると思いますが、実際には記載されていません。

Cのバイナリゼロでは'\0'は文字列を終了し、それ自体で空の文字列を表します。 BashはCで書かれているので、おそらくそれから続くでしょう。

編集:POSIXは多くの場所でnull文字列に言及しています。 「基本定義」では、null文字列を次のように定義します。

.146空の文字列(またはヌル文字列)
最初のバイトがヌルバイトである文字列。

3
cdarke