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