我如何评估两个命令?

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。如何执行包含两个或多个命令的字符串?

Sté*_*las 7

在 中$(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 会看到两个“单词”:evalecho 'a'; echo 'b'。同样,这些将构成从第一个派生的命令的参数。

这里的命令是 shell 的eval内置命令。同样,eval忽略它的第一个参数。它所做的是用空格连接其他参数(这里只有一个),并将结果字符串解释为 shell 代码。口译时

echo 'a'; echo 'b'
Run Code Online (Sandbox Code Playgroud)

shell 看到一个不带引号的;分隔命令。第一个被视为一个简单的命令,最终echo以两个参数调用......等等。