反斜杠在反引号中到底是如何工作的?
来自 Bash 常见问题解答:
反引号内的反斜杠 (\) 以不明显的方式处理:
$ echo "`echo \\a`" "$(echo \\a)" 一个\一个 $ echo "`echo \\\\a`" "$(echo \\\\a)" \a \a
但 FAQ 并没有分解导致这种差异的解析规则。我发现的来自 man bash
的唯一相关引用是:
当使用旧式反引号形式的替换时,反斜杠保留其字面含义,除非后面跟着 $、` 或 .
"$(echo \\a)"
和 "$(echo \\\\a)"
情况很简单:反斜杠,转义字符,正在转义自身变成了字面上的强烈反对。因此,\\
的每个实例在输出中都变为 \
。但我正在努力理解反引号情况的类似逻辑。基本规则是什么以及观察到的输出是如何得出的?
最后,一个相关的问题...如果您不引用反引号,则会收到“不匹配”错误:
$ echo `echo \\\\a`
-bash: no match: \a
这种情况下发生了什么?
更新
回复:我的主要问题,我有一套规则的理论可以解释所有的行为,但仍然不知道它是如何从 bash 中记录的规则中得出的。这是我建议的规则......
在反引号内,字符前面的反斜杠只是返回该字符。即,单个反斜杠没有效果。对于所有字符都是如此,除了反斜杠本身和反引号。对于反斜杠本身,\\
变成转义反斜杠。它将转义下一个字符。
让我们看看这个例子是如何实现的:
a=xx
echo "`echo $a`" # prints the value of $a
echo "`echo \$a`" # single backslash has no effect: equivalent to above
echo "`echo \\$a`" # escaping backslash make $ literal
prints:
xx
xx
$a
让我们从这个角度分析一下原始示例:
echo "`echo \\a`"
这里 \\
产生转义反斜杠,但是当我们“转义”a
,我们只是返回a
,所以它打印a
。
echo "`echo \\\\a`"
这里第一对 \\
产生一个转义反斜杠,该反斜杠应用于 \
,产生一个文字反斜杠。也就是说,前 3 个 \\\
在输出中成为单个文字 \
。剩余的 \a
仅生成 a
。最终结果是\a
。
From the Bash FAQ:
Backslashes (\) inside backticks are handled in a non-obvious manner:
$ echo "`echo \\a`" "$(echo \\a)" a \a $ echo "`echo \\\\a`" "$(echo \\\\a)" \a \\a
But the FAQ does not break down the parsing rules that lead to this difference. The only relevant quote from man bash
I found was:
When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $, `, or .
The "$(echo \\a)"
and "$(echo \\\\a)"
cases are easy enough: Backslash, the escape character, is escaping itself into a literal backlash. Thus every instance of \\
becomes \
in the output. But I'm struggling to understand the analogous logic for the backtick cases. What is the underlying rule and how does the observed output follow from it?
Finally, a related question... If you don't quote the backticks, you get a "no match" error:
$ echo `echo \\\\a`
-bash: no match: \a
What's happening in this case?
update
Re: my main question, I have a theory for a set of rules that explains all the behavior, but still don't see how it follows from any of the documented rules in bash. Here are my proposed rules....
Inside backticks, a backslash in front of a character simply returns that character. Ie, a single backslash has no effect. And this is true for all characters, except backlash itself and backticks. In the case of backslash itself, \\
becomes an escaping backslash. It will escape its next character.
Let's see how this plays out in an example:
a=xx
echo "`echo $a`" # prints the value of $a
echo "`echo \$a`" # single backslash has no effect: equivalent to above
echo "`echo \\$a`" # escaping backslash make $ literal
prints:
xx
xx
$a
Let's analyze the original examples from this perspective:
echo "`echo \\a`"
Here the \\
produces an escaping backslash, but when we "escape" a
we just get back a
, so it prints a
.
echo "`echo \\\\a`"
Here the first pair \\
produces an escaping backslash which is applied to \
, producing a literal backslash. That is, the first 3 \\\
become a single literal \
in the output. The remaining \a
just produces a
. Final result is \a
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
逻辑非常简单。因此,我们查看 bash 源代码 (4.4) 本身
subst.c:9273
正如您所看到的,在字符串上调用函数
de_backslash(temp);
来更新字符串c.相同功能的代码如下subst.c:1607
相同的输出是
)) i++; prev_i = i; ADVANCE_CHAR(string, slen, i); if (j < prev_i) do string[j++] = string[prev_i++]; while (prev_i < i); else j = i; } string[j] = '\0'; return (string); }\\$a
。现在让我们在 bash 中测试相同的内容如果有
\
字符并且下一个字符是\
,上面的代码只是做简单的事情或者反引号或$
,然后跳过这个\
字符并复制下一个字符所以如果为了简单起见将其转换为python
相同的输出是
\\$a
。现在让我们在 bash 中测试相同的内容The logic is quite simple as such. So we look at bash source code (4.4) itself
subst.c:9273
As you can see calls a function
de_backslash(temp);
on the string which updates the string in c. The code the same function is belowsubst.c:1607
The output of the same is
)) i++; prev_i = i; ADVANCE_CHAR(string, slen, i); if (j < prev_i) do string[j++] = string[prev_i++]; while (prev_i < i); else j = i; } string[j] = '\0'; return (string); }\\$a
. And now lets test the same in bashThe above just does simple thing if there is
\
character and the next character is\
or backtick or$
, then skip this\
character and copy the next characterSo if convert it to python for simplicity
The output of the same is
\\$a
. And now lets test the same in bash做了更多的研究来找到正在发生的事情的参考和规则。从 GNU Bash 参考手册中指出
换句话说,`` 中的 \、\$ 和 ` 在命令替换之前由 CLI 解析器处理。其他所有内容都会传递给命令替换进行处理。
让我们逐步了解问题中的每个示例。在 # 之后,我放置了在执行 `` 或 $() 之前 CLI 解析器如何处理命令替换。
你的第一个例子解释了。
您的第二个示例解释:
您的第三个示例:
您的第三个示例使用 $()
Did some more research to find the reference and rule of what is happening. From the GNU Bash Reference Manual it states
In other words \, \$, and ` inside of `` are processed by the CLI parser before the command substitution. Everything else is passed to the command substitution for processing.
Let's step through each example from the question. After the # I put how the command substitution was processed by the CLI parser before `` or $() is executed.
Your first example explained.
Your second example explained:
Your third example:
Your third example using $()