Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 为什么$'\0';或$'\x0';是空字符串吗?应为空字符,isn';不是吗?_Bash_String_Echo_Expansion_Dollar Sign - Fatal编程技术网

Bash 为什么$'\0';或$'\x0';是空字符串吗?应为空字符,isn';不是吗?

Bash 为什么$'\0';或$'\x0';是空字符串吗?应为空字符,isn';不是吗?,bash,string,echo,expansion,dollar-sign,Bash,String,Echo,Expansion,Dollar Sign,允许$”字符串“扩展。我的manbash说: 对$”字符串形式的单词进行特殊处理。 单词扩展为字符串,并按照ANSI C标准的规定替换反斜杠转义字符。 反斜杠转义序列(如果存在)解码如下: \a警报(铃声) \b退格 \e \E转义字符 \f表单提要 \n新行 \r回车 \t水平选项卡 \v垂直选项卡 \反斜杠 \'单引号 \”双引号 \nnn其值为八进制值的八位字符nnn(一到三位) \xHH其值为十六进制值的八位字符HH(一个或两个十六进制数字) \cxa控件-x字符 扩展后的结果是单引号,

允许
$”字符串
扩展。我的
manbash
说:

$”字符串形式的单词进行特殊处理。
单词扩展为
字符串
,并按照ANSI C标准的规定替换反斜杠转义字符。 反斜杠转义序列(如果存在)解码如下:
\a
警报(铃声)
\b
退格
\e

\E
转义字符
\f
表单提要
\n
新行
\r
回车
\t
水平选项卡
\v
垂直选项卡
\
反斜杠
\'
单引号
\”
双引号
\nnn
其值为八进制值的八位字符
nnn
(一到三位)
\xHH
其值为十六进制值的八位字符
HH
(一个或两个十六进制数字)
\cx
a控件-
x
字符

扩展后的结果是单引号,就好像美元符号不存在一样

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

它有文档记录吗?有原因吗?(它是一个特性还是一个限制,甚至是一个bug?)

我的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'
不同?

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

空字符表示一个空字符串,这是您在展开它时得到的。这是一个特殊情况,我认为文档中暗示了这一点,但实际上没有说明

在C中,二进制零
“\0”
终止一个字符串,并且它本身也表示一个空字符串。Bash是用C编写的,因此它可能就是这样

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

3.146空字符串(或空字符串)
第一个字节为空字节的字符串

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

因为空字符终止字符串

$ echo $'hey\0you'
hey

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

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

3.92字符串

结尾并包含第一个空字节的连续字符序列

同样,标准C对于字符串中的NUL字符也相当明确:

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

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

在这种情况下,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

问得好!可能是Posix的问题?祝你好运。谢谢你的回答。我在使用netcat测试服务器的SGCI接口时遇到了同样的问题。SCGI头有NUL字符。在阅读了这里,特别是关于使用管道的建议后,我开发了一个解决方法。我使用了octal 377(ASCII 255)在需要NUL字符的地方,然后通过tr将字符串传递到netcat xmlreq='system.client版本'scgihdr=CONTENT_LENGTH$'\377'${{xmlreq}$'\377'SCGI$'\377'1$'\377'echo-n${{scgihdrGreat info.Re:“没有任何东西可以阻止您将shell变量分配给输出NUL的程序的输出-值得指出的是,变量的值总是在遇到第一个NUL时被截断。Re“如果使用bash的反斜杠转义序列($'\0')将NUL插入字符串,它将终止该值。”-澄清一下:在另一个字符串中插入
$'\0'
不会终止整个字符串,而只是忽略
$'\0'
;例如,
a$'\0'b
->
ab
;在
$'.
中插入
\0
,但是,会在那里切断该字符串;例如,
$'a\0b'
-
@mklemt两年前这是错的。谢谢。现在我相信已经修复了。谢谢更新。将命令输出重新分配给变量:鉴于
bash
变量值在内部存储为C字符串,它们永远不能包含
$ echo $'hey\0you'
hey
$ # 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