![带引号的字符串中的命令替换与反斜杠转义](https://linux22.com/image/5887/%E5%B8%A6%E5%BC%95%E5%8F%B7%E7%9A%84%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E7%9A%84%E5%91%BD%E4%BB%A4%E6%9B%BF%E6%8D%A2%E4%B8%8E%E5%8F%8D%E6%96%9C%E6%9D%A0%E2%80%8B%E2%80%8B%E8%BD%AC%E4%B9%89.png)
考虑使用双引号命令替换,其中包含反斜杠转义符,如下所示:
echo "$(echo '\\')"
它打印出\\
,而我原本期望它只打印出一个反斜杠。我的想法(这是不正确的)是它遍历了整个字符串,替换了所有反斜杠转义符,并且然后它将进行命令替换。显然,顺序是相反的。
但是,如果我们这样做
echo "$(echo '\')$"
它打印出来\$
。我预计如果它正在执行命令替换第一的然后评估该字符串的反斜杠转义符, the\
和 the最终$
可能组合成一个单一的。$
但事实并非如此。
反斜杠转义符在哪里适合事物的顺序?
(这个问题的背景是我正在研究一些可以正确转义字符串中的正则表达式字符以插入 sed 命令的方法。)
答案1
我认为最好通过echo $(echo '\\')
(即不带外引号的变体)的输出来理解它,这会导致\\
.重点是没有文字字符串$(...)
扩展命令替换实体时反斜杠的解释。 (这与在字符串中存储转义字符的情况类似;不会将其重新解释为文字字符串。)
答案2
在用 分隔的命令替换中$(…)
,括号内的内容将以与顶级命令相同的方式进行解析(除了一些涉及不平衡右括号的极端情况)。括号内是一个普通的 shell 片段,没有进行额外的反斜杠扩展。
该命令echo '\\'
打印三个字符:两个反斜杠和一个换行符(假设echo
命令不进行反斜杠扩展)。因此,命令替换的结果$(echo '\\')
是两个字符的字符串\\
(最后的换行符被删除,命令替换总是这样做)。由于您在双引号内使用了命令替换,因此不会执行其他扩展:结果单词部分是\\
。
在 中echo "$(echo '\')$"
,命令替换输出一个反斜杠。它对参数 的贡献echo
是字符串\
。以下后面的$
字符不能作为参数名称的起始字符,因此它会扩展为自身。因此 echo 的参数是两个字符的字符串\$
。双引号字符串不会进一步扩展,没有任何东西可能导致反斜杠被解释为特殊字符(命令的某些风格除外echo
)。
您可以在 shell 手册和其他文档中查找完整的扩展规则,具有不同程度的可读性。这POSIX规范按照标准来说还不错(微弱的赞扬)。
答案3
它与引用有更多关系,
$ echo '\'
\
$ echo '\\'
\\
$ echo "\\"
\
使用单引号时,引号之间的任何内容都会被回显。使用双引号,shell 会查看内部并进行处理。