命令替换中的Bash引用
我很难理解这一点。 以下命令用于展开文件:命令替换中的Bash引用,bash,Bash,我很难理解这一点。 以下命令用于展开文件: % echo "(echo " * " )" (echo foo.txt bar.txt ) 但事实并非如此 % echo "$(echo " * " )" * 星号*不带引号。这两种情况下不都应该发生文件全球化吗?命令替换如何影响这种情况 % echo "$(echo " * " )" # --------|--------| #produces | | # echo " * " 这是一个引用的* 对于您显
% echo "(echo " * " )"
(echo foo.txt bar.txt )
但事实并非如此
% echo "$(echo " * " )"
*
星号*不带引号。这两种情况下不都应该发生文件全球化吗?命令替换如何影响这种情况
% echo "$(echo " * " )"
# --------|--------|
#produces | |
# echo " * "
这是一个引用的*
对于您显示的外部echo
,相同,cmd替换的输出被引用,您只看到一个*
也就是说,$(..)
中的内容在执行封闭命令之前进行处理
IHTH单独查看这些命令很有帮助
% echo "(echo " * " )"
…只有一个引用上下文。在这里,(echo
被引用,一个*
被给出而不被引用,然后一个)
被给出而被引用
这里,您正在执行一个命令替换,内部命令有自己的引用上下文。具体而言,该内部命令是:
# the inner command for the substitution is run first
echo " * "
…正如人们所期望的那样,它以*
作为输出。值得注意的是,因为它有自己的引用上下文,所以内容开始时不带引号,只有在看到“
时才会被引用
然后,执行替换;因为$()
在引号内,所以该替换过程不会运行字符串拆分和全局扩展(如果遵循这些步骤,则会将内部命令的输出拆分为多个字,并将每个字作为全局扩展)
…因此成为
# effectively single-quoted because we already finished running expansions
# so expansions that would be allowed in double-quotes are already finished
echo ' * '
相比之下,如果您没有引用:
echo $(echo "*")
…将成为
echo *
…其行为符合您的预期
或者,反过来说
echo "$(echo *)"
…将成为类似于
echo 'foo.txt bar.txt'
如果说第二个引号中没有星号,这是不准确的。
$()
会打开一个新的引用上下文——因此,只有在打开引号时,引号才会在该场景中开始。相反,使用()
,没有打开新的上下文。@CharlesDuffy我想这就是答案,请这样说:)我接受了,因为这给出了一个更完整的解释。问题是bash参考手册()没有详细说明任何嵌套情况。另外,尽管我听说过这种“命令替换”有自己的引用上下文“在stackoverflow中有几次,它在bash手册中奇怪地丢失了。bash遵循POSIX sh规范,$()
就是从那里来的。如果你想要一个规范化的语言引用,那就是head的方法。请参阅中的第2.2.3节和第2.3节规则5。你是对的。我正在寻找能够解决歧义情况的语言规范。2.2.3明确规定了我想知道的内容。谢谢
echo "$(echo *)"
echo 'foo.txt bar.txt'