Ben*_*ird 3 shell bash quoting
如果我运行这个:
echo "echo 'a'; echo 'b'"
Run Code Online (Sandbox Code Playgroud)
它产生一个我可以运行的字符串,它可以工作 - echoes a\nb\n
。
但是,这不起作用:
$(echo "echo 'a'; echo 'b'")
Run Code Online (Sandbox Code Playgroud)
为什么不?它不适用于任何命令,而不仅仅是 echo。如何执行包含两个或多个命令的字符串?
在 中$(echo "echo 'a'; echo 'b'")
,shell 看到一个命令替换。就是这样。所以这将是一个简单的命令,其参数是命令替换扩展时 split+glob 运算符的结果。
shell 将获取echo "echo 'a'; echo 'b'"
命令的输出,在这种情况下echo 'a'; echo 'b'\n
,删除尾随的换行符echo 'a'; echo 'b'
,以便根据$IFS
变量的值将其拆分。
如果$IFS
尚未从其默认改变,这将是4个字:echo
,'a';
,echo
和'b'
。这些词中的每一个都将受到通配。在这里,没有一个包含通配符,所以这些词将保持原样。
所以我们有 4 个参数来运行一个简单的命令。第一个参数将用于派生要运行的命令。echo
是内置的大多数shell。因此,shell 将echo
使用这 4 个参数调用其内置函数。
echo
忽略它的第一个(第 0 个)参数并输出由空格字符分隔并以换行符终止的其他参数。一些echo
实现扩展了反斜杠转义序列,但这里没有。所以echo
会输出:
'a'; echo 'b'\n
Run Code Online (Sandbox Code Playgroud)
如果你想评估它,也就是说,如果你想将该字符串解释为 shell 代码,请使用eval
:
eval "echo 'a'; echo 'b'"
Run Code Online (Sandbox Code Playgroud)
这也被认为是一个简单的命令。由于引号,shell 会看到两个“单词”:eval
和echo 'a'; echo 'b'
。同样,这些将构成从第一个派生的命令的参数。
这里的命令是 shell 的eval
内置命令。同样,eval
忽略它的第一个参数。它所做的是用空格连接其他参数(这里只有一个),并将结果字符串解释为 shell 代码。口译时
echo 'a'; echo 'b'
Run Code Online (Sandbox Code Playgroud)
shell 看到一个不带引号的;
分隔命令。第一个被视为一个简单的命令,最终echo
以两个参数调用......等等。