为什么$'\ 0'或$'\ x0'是一个空字符串?应该是空字符,不是吗?

时间:2013-10-07 14:33:43

标签: string bash echo expansion dollar-sign

允许$'string'扩展。我的man bash说:

  

$'string'形式的单词是专门处理的。   该单词扩展为 string ,替换为ANSI C标准指定的反斜杠转义字符。   反斜杠转义序列(如果存在)按如下方式解码:
            \a警报(铃声)
            \b退格             \e
            \E逃脱角色
            \f表格Feed             新\n新行             \r回车
            \t水平标签
            \v垂直标签
            \反斜杠             \'单引号
            \"双引号             \nnn八位字符,其值为八进制值 nnn (一到三位数)
            \xHH八位字符,其值为十六进制值 HH (一个或两个十六进制数字)
            \cx控件 - x 字符

     

展开的结果是单引号,好像美元符号不存在一样。

但是为什么没有将$'\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'

3 个答案:

答案 0 :(得分:24)

这是一个限制。 bash不允许字符串值包含内部NUL字节。

Posix(和C)字符串不能包含内部NUL。例如,请参阅字符串的Posix definition(强调添加):

  

3.92字符串

     

连续的字符序列结尾,包括第一个空字节

类似地,标准C对字符串中的NUL字符是合理明确的:

  

§5.2.1p2...所有位都设置为0的字节,称为空字符,应存在于基本执行字符集中;它用于终止字符串。

Posix明确禁止在文件名(XBD 3.170)或环境变量中使用NUL(和/)(XBD 8.1“...被视为以空字节结尾。”

在这种情况下,shell命令语言(包括bash)倾向于使用相同的字符串定义,作为由单个NUL终止的非NUL字符序列。

当然,您可以通过bash管道自由传递NUL,并且没有什么能阻止您将shell变量分配给输出NUL字节的程序的输出。但是,根据Posix(XSH 2.6.3“如果输出包含任何空字节,则行为未指定。”),后果是“未指定的”。在bash中,除非使用bash的C-escape语法($'\0')将NUL插入到字符串中,否则将删除NUL,在这种情况下,NUL将最终终止该值。

实际上,请考虑以下两种尝试将NUL插入实用程序stdin的方法之间的区别:

$ # 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

答案 1 :(得分:5)

  

但为什么bash不会将$'\0'$'\x0'转换为空字符?

因为空字符终止了字符串。

$ echo $'hey\0you'
hey

答案 2 :(得分:3)

这是一个空字符,但它取决于你的意思。

null字符表示一个空字符串,这是您展开它时得到的。这是一个特例,我认为这是由文档暗示的,但没有实际说明。

在C二进制文件中,零'\0'终止一个字符串,它本身也代表一个空字符串。 Bash是用C语言编写的,所以可能就是这样。

编辑:POSIX在许多地方提到一个空字符串。在“基本定义”中,它将空字符串定义为:

  

3.146空字符串(或空字符串)
  一个字符串,其第一个字节是空字节。