如果我运行这个:
echo "echo 'a'; echo 'b'"
它会生成一个字符串,然后我可以运行该字符串,并且它可以工作 - echoes a\nb\n
。
但是,这不起作用:
$(echo "echo 'a'; echo 'b'")
为什么不?它不适用于任何命令,而不仅仅是 echo。如何执行包含两个或多个命令的字符串?
答案1
在 中$(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
如果你想评估它,也就是说,如果你想将该字符串解释为 shell 代码,请使用eval
:
eval "echo 'a'; echo 'b'"
这也被认为是一个简单的命令。由于引号,shell 会看到两个“单词”:eval
和echo 'a'; echo 'b'
。同样,这些将构成从第一个派生的命令的参数。
这里的命令是shell的eval
内置命令。再次eval
忽略它的第一个论点。它的作用是将其他参数(这里只有一个)与空格连接起来,并将结果字符串解释为 shell 代码。口译时
echo 'a'; echo 'b'
shell 看到一个未加引号的;
命令来分隔命令。第一个被视为一个简单的命令,最终echo
以两个参数调用......等等。
答案2
if eval "( service networking restart &> /dev/null && ping -c3 google.com &> /dev/null )"; then
echo "service is running"
else
echo "service is not running"
fi