【问题标题】:Trouble understanding the non-obvious use of backslash inside of backticks无法理解反引号内反斜杠的非明显使用
【发布时间】:2020-05-08 22:54:18
【问题描述】:

我已经阅读了大量页面,包括 bash 手册,但仍然发现反斜杠的“非显而易见”使用令人困惑。

如果我这样做:

echo \*

它打印一个星号,这是正常的,因为我正在逃避星号使其成为文字。

如果我这样做:

echo \\*

它打印\* 这似乎也很正常,第一个反斜杠转义了第二个。

如果我这样做了

echo `echo \\*`

它打印目录的内容。但在我看来,它应该与echo \\* 打印相同,因为当它被替换并传递给 echo 时。我知道这是每个人都在谈论的不明显的反斜杠使用,但我很难理解为什么会发生这种情况。

bash 手册也说

当使用旧式反引号形式的替换时,反斜杠保留其字面含义,除非后面跟着“$”、“`”或“\”。

但它没有定义“反斜杠的字面意思”是什么。它是作为转义字符、延续字符还是只是字面上的反斜杠字符?

另外,它说它保留了它的字面意思,除非后面跟着......那么当它后面跟着这三个字符之一时,它会做什么?它只逃避这三个字符吗?

【问题讨论】:

  • “字面意思”表示它实际上是字符串中的一个 ASCII 码点 92,而不是有向图的一部分。
  • 请注意echo \\*echo $(echo \\*) 打印相同的内容,并且$() 通常是在子shell 中调用命令的首选方法。

标签: bash backslash


【解决方案1】:

这主要是出于历史兴趣,因为`...` 命令替换已被更清洁的$(...) 形式取代。任何新脚本都不应该使用反引号。

这是您评估 $(command) 替换的方式

  1. 运行命令

以下是评估`string` 命令替换的方法:

  1. 确定字符串的跨度,从开始反引号到结束未转义反引号(如果此反引号在字符串文字内,则行为未定义:shell 通常会将其视为文字反引号或关闭反引号,具体取决于其解析器实现)
  2. 通过删除美元、反引号或反斜杠这三个字符之一之前的反斜杠来取消对字符串的转义。然后将下面的字符按字面意思插入到命令中。后跟任何其他字符的反斜杠将被单独保留。
    • 例如Hello\\ World 将变为 Hello\ World,因为 \\ 被替换为 \
    • Hello\ World 也将变为 Hello\ World,因为反斜杠后面跟着一个不是这三个字符之一的字符,因此保留了其作为反斜杠的字面意义
    • \\\* 将变为 \\*,因为 \\ 将变为 \(因为反斜杠是三者之一),而 \* 将保持为 \*(因为星号不是)
  3. 将结果评估为 shell 命令(这包括对现在未转义的命令字符串的结果遵循所有常规 shell 转义规则)

所以要评估echo `echo \\*`

  1. 确定字符串的跨度,这里是echo \\*
  2. 根据反引号引用规则取消转义:echo \*
  3. 将其评估为命令,该命令运行 echo 以输出文字 *
  4. 由于替换的结果没有被引用,输出将经历:
    1. 分词:* 变为 *(因为只有一个词)
    2. 每个单词的路径名扩展,所以*根据当前目录中的文件变为binDesktopDownloadsPhotospublic_html
    3. 请特别注意,这与将反引号命令替换为输出并重新运行结果相同。例如,我们没有考虑输出中的转义、引号和扩展,而简单的基于文本的宏扩展会具有这些。
  5. 将这些中的每一个作为参数传递给下一个命令(也是回显):echo bin Desktop Downloads Photos public_html

结果是当前目录中的文件列表。

【讨论】:

  • ...这就是为什么我们更喜欢$( ) 而不是反引号。
  • 因此手册可以阅读(以简化)当使用旧式反引号形式的替换时,反斜杠是文字反斜杠,除非后跟美元符号、反引号或其他反斜杠,其中如果它被删除?这是一个准确的说法吗?
  • @Vonedaddy 虽然不完整,但它是准确的。例如,它没有明确说 \\\\ 应该变成 \\ ,即使 3 个反斜杠后面跟着另一个反斜杠,虽然它说 \` 应该变成 `,但它没有明确说它那么应该终止替换。
  • 明白。但是手册中的第二行将涵盖反引号终止。它指出前面没有反斜杠的第一个反引号终止命令替换。非常感谢您的故障。它真的帮助我了解它是如何工作的。非常感谢您。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-24
  • 2014-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 1970-01-01
相关资源
最近更新 更多