的POSIX shell标准
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_07_04
在第2.6节中说:
command substitution (...) shall be performed
(...)
Quote removal (...) shall always be performed last.
在我看来,在命令替换后不执行引用删除:
$ echo "#"
#
$ echo '"'
"
正如所料,但
$ echo $(echo '"')#"
>
我不理解什么?
阅读答案/评论后添加:
从每个人的意见来看,引用的考虑发生在解析的最开始,例如,以确定命令是否是可接受的"。那么为什么标准还要强调,引用删除是在过程的后期执行的?
答案 0 :(得分:1)
"然后外部命令变为
echo "#"
并且是平衡的"
那不是平衡的'因为第一个双引号不计数。如果引号在命令行中不受阻碍,则它们仅作为引号有意义。
要验证,请查看以下内容:
$ echo $(echo '"')#
"#
这是平衡的,因为shell确实认为"
只是另一个角色。
相比之下,这是不平衡的,因为它只有一个shell活动"
:
$ echo $(echo '"')#"
>
这里我们展示相同的东西,但使用参数扩展而不是命令替换:
$ q='"'; echo $q
"
一旦shell将"
替换为$q
,人们可能会认为存在不平衡的双引号。但是,双引号是参数扩展的结果,因此不是一个shell活动引用。
我们考虑一个包含file
的目录:
$ ls
file
$ ls "file"
file
正如您在上面所看到的那样,在ls
运行之前已经执行了引用删除。
但是,请考虑以下命令:
$ echo ls $(echo '"file"')
ls "file"
正如您所见,ls $(echo '"file"')
扩展为ls "file"
,这是上面成功运行的命令。现在,让我们尝试运行:
$ ls $(echo '"file"')
ls: cannot access '"file"': No such file or directory
如您所见,shell不会处理命令替换后保留的双引号。这是因为这些引号不被认为是shell活动的。因此,它们被视为普通字符并传递给ls
,它抱怨名称以"
开头和结尾的文件在目录中不存在。
这里也发生了同样的事情:
$ cmd='ls "file"'
$ $cmd
ls: cannot access '"file"': No such file or directory
用单引号括起字符('')应保留 单引号中每个字符的字面值
换句话说,一旦双引号出现在单引号内,它就没有特殊的权力:它只是另一个字符。
该标准还提到了转义和双引号作为保留"字面值的方法"一个角色。
刚接触shell的人通常希望将命令存储在变量中,如上面的cmd='ls "file"'
示例所示。但是,因为引号和其他shell-active字符一旦存储在变量中就不再是shell活动的,复杂的情况总是会失败。这导致了一篇经典论文:
"I'm trying to put a command in a variable, but the complex cases always fail!"