23

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

フォームの単語は特別に扱われます。単語は に展開され、バックスラッシュでエスケープされた文字は ANSI C 標準の指定に従って置き換えられます。 バック スラッシュ の エスケープ シーケンス が 存在 する場合は、次のよう に デコード さ れ ます 。 数字) 値が 16 進数値である 8 ビット文字$'string'string
\a
\b
\e
\E
\f
\n
\r
\t
\v
\
\'
\"
\nnnnnn
\xHHHH(1 桁または 2 桁の 16 進数) 制御文字
\cxx

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

しかし、なぜはヌル文字に変換されない$'\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'ですか?

4

3 に答える 3

27

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

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

3.92 文字列

最初の null バイトで終了し、最初の null バイトを含む連続した文字シーケンス。

同様に、標準 C は、文字列の NUL 文字について合理的に明示しています。

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

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

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

もちろん、bash パイプを介して自由に NUL を渡すことができ、NUL バイトを出力するプログラムの出力にシェル変数を割り当てることを妨げるものは何もありません。ただし、Posix によると、結果は「未規定」です (XSH 2.6.3「出力に null バイトが含まれている場合、動作は規定されていません。」)。bash では、bash の C エスケープ構文 ( ) を使用して NUL を文字列に挿入しない限り、NUL は削除されます$'\0'。この場合、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
于 2013-10-07T15:54:39.503 に答える
4

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

null 文字は空の文字列を表し、それを展開すると表示されます。これは特殊なケースであり、ドキュメントで暗示されていると思いますが、実際には述べられていません。

C では、2 進数のゼロ'\0'は文字列を終了し、単独でも空の文字列を表します。Bash は C で書かれているので、おそらくそれに倣うのでしょう。

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

3.146 空の文字列 (または Null 文字列)
最初のバイトが null バイトである文字列。

于 2013-10-07T14:48:34.167 に答える