为什么这不起作用?
显然是因为 Bash 在 ANSI-C 引用方面存在长期的行为不一致。
它的 ANSI-C 引用文档没有任何上下文异常。
它的 heredocs 文档没有做出任何似乎相关的特殊规定:
如果[分隔符]不加引号,则here-document的所有行都经过参数扩展、命令替换和算术扩展,字符序列\newline
被忽略,必须使用'\'来引用字符'\', '$' 和 '`'。
因为我认为最后一句话暗示了“为了消除它们的特殊意义”,我在那里或在参数扩展的描述中看不到任何东西表明参数扩展在heredoc中的工作方式与在其他地方的工作方式不同。
但显然,确实如此。具体来说,ANSI-C 引用的字符串在 heredocs 之外的参数扩展中被识别,但在词汇表中与 heredocs 内的相同参数扩展不同。这似乎会影响所有形式的参数扩展,其中将参数名称以外的文本作为扩展的一部分,并且它不依赖于任何 C 样式转义序列的使用。例子:
$ ex1=abcdef
$ cat <<<${ex1#*$'b'}
cdef
$ cat <<EOF
${ex1#*$'b'}
EOF
abcdef
ex2=a\$bcdef
$ cat <<<${ex2%$'b'*}
a$
$ cat <<EOF
${ex2%$'b'*}
${ex2/$'b'/X}
EOF
a
aXcdef
实际的行为似乎是$
引入 C 风格的引号被视为文字字符,但单引号被解释为根据它们作为引号字符的普通角色。最简单的解决方法似乎是将 ANSI-C 引用的文本分配给一个变量:
var=$'b'
$ cat <<EOF
${ex1/${var}/X}
EOF
aXcdef
我首先倾向于猜测这种行为差异与 ANSI-C 引用没有直接在heredoc 的正文中被识别有关。但是,在 heredocs 中也不能直接识别单引号或双引号的引用,但是这些引用形式仍然可以在嵌入在 heredocs 中的参数扩展中识别。我很难理解为什么不应该将某些参数扩展在 heredocs 内部的解释与在外部解释不同的错误视为错误。