bash中的双引号如何匹配(配对)?

Wei*_*hou 15 bash quoting wildcards

我正在使用GNU bash 4.3.48. 考虑以下两个仅相差一个美元符号的命令。

命令 1:

echo "(echo " * ")"
Run Code Online (Sandbox Code Playgroud)

命令 2:

echo "(echo " * ")"
Run Code Online (Sandbox Code Playgroud)

它们的输出分别为

(echo  test.txt ppcg.sh )
Run Code Online (Sandbox Code Playgroud)

 * 
Run Code Online (Sandbox Code Playgroud)

所以很明显,在第一种情况下,the *is globbed,这意味着第一个引号与第二个组成一对,第三个和第四个组成另一对。

在第二种情况下,the *is not globbed,并且输出中正好有两个额外的空格,一个在星号之前,一个在星号之后,这意味着第二个引号与第三个一起,第一个与第四个一起。

除了$()引号与下一个不匹配,而是嵌套的构造之外,还有其他情况吗?这种行为是否有详细记录,如果有,我在哪里可以找到相应的文档?

Mic*_*mer 14

任何可以插入字符串内部的嵌套结构都可以在其中包含更多字符串:它们像新脚本一样被解析,直到结束标记,甚至可以嵌套多级深度。所有酒吧之一都以$. 所有这些都记录在 Bash 手册和 POSIX shell 命令语言规范的组合中。

这些构造有几种情况:

  • $( ... )如您所见,用替换命令POSIX 指定了这种行为

    对于$(command)表单,左括号后面到匹配右括号的所有字符构成命令。任何有效的 shell 脚本都可用于命令...

    引号是有效的 shell 脚本的一部分,因此它们的正常含义是允许的。

  • 命令替换也使用`
  • 高级参数替换实例${parameter:-word}的“word”元素,例如. “词”定义是

    被 shell 视为一个单元的字符序列

    - 包括引用文本甚至混合引号a"b"c'd'e- 尽管扩展的实际行为比这更自由一些,例如也${x:-hello world}可以工作。

  • 算术扩展$(( ... )),虽然它在很大程度上是无用的存在(但你可以嵌套命令替换或变量的扩张,也再有引号里面有用的)。POSIX 指出

    表达式应被视为在双引号中,除非表达式中的双引号没有被特殊处理。shell 应扩展表达式中的所有标记以进行参数扩展、命令替换和引号删除。

    所以这种行为是明确要求的。这意味着进行echo "abc $((4 "*" 5))"算术运算,而不是通配符。

    不过,请注意旧式$[ ... ]算术扩展以相同方式处理:如果它们出现的报价将是一个错误,不管扩张引述与否。此表单不再被记录在案,无论如何也不打算使用。

  • 带有 的特定于区域设置的翻译$"...",它实际上使用"作为核心元素。$"被视为一个单元。

还有一种你可能没有想到的嵌套情况,不涉及引号,它是大括号扩展{a,b{c,d},e}扩展为“a bc bd e”。${x:-a{b,c}d}确实没有然而窝; 它被视为参数替换,给出“ a{b,c”,后跟“ d}”。这也记录在案

当使用大括号时,匹配的结束大括号是第一个没有被反斜杠或带引号的字符串转义的 '}',并且不在嵌入式算术扩展、命令替换或参数扩展中。


作为一般规则,所有分隔的构造都独立于周围的上下文来解析它们的主体(并且异常被视为错误)。从本质上说,在看到$(命令替换的代码只是要求解析器从身体消耗所能,就好像它是一个新的程序,然后检查,预期结束标志(一个转义)))})出现一次子解析器运行它可以消耗的东西。

如果您考虑递归下降解析器的功能,那只是对基本情况的简单递归。一旦你有了字符串插值,它实际上比其他方式更容易做。不管底层的解析技术如何,支持这些结构的 shell 都会给出相同的结果。

您可以通过这些结构尽可能深入地嵌套引用,它会按预期工作。看到中间的引用不会让任何地方感到困惑;相反,这将是内部上下文中新的带引号的字符串的开始。

  • `"${var-"foo"}"` 的处理有很多变化(`echo "${-+"*"}"` 与 Bourne 或 Korn shell 中的 `echo *` 相同例如)和[该行为将在下一版标准中明确未指定](http://austingroupbugs.net/view.php?id=221#c399)。另见 https://www.mail-archive.com/austin-group-l@opengroup.org/msg00167.html 上的讨论 (2认同)