如果我将cat命令保存到字符串然后执行它,那么我将收到错误
linux# cmd="cat /data/test/test.tx* | grep toto"
linux# eval '$cmd'
cat: |: No such file or directory
cat: grep: No such file or directory
cat: toto: No such file or directory
即使
linux# $cmd
cat: |: No such file or directory
cat: grep: No such file or directory
cat: toto: No such file or directory
我知道
linux# eval "$cmd"
有效,但在我的脚本中我想使用eval '$cmd'
如何将cat命令保存到变量中时执行它?
现在,如果cmd="echo anymessage"
那么
linux# eval '$cmd'
linux# $cmd
linux# eval "$cmd"
所有这些都可以使用
答案 0 :(得分:5)
让我们从一个简单的命令开始,它可以以任何方式工作,但出于不同的原因。
$ cmd="echo anymessage"
$ eval '$cmd'
eval '$cmd'
eval
处理字符串$cmd
。它将它分成单词,这又是单个单词$cmd
。它将参数扩展为echo anymessage
并执行一轮分词以获得echo
和anymessage
。现在,echo
是命令,anymessage
是参数,执行echo
命令。
$ eval "$cmd"
此处,eval
正在处理字符串echo anymessage
,因为bash
在执行$cmd
之前已在eval
上执行了参数展开。该字符串再次拆分为单词,echo
被识别为命令。
现在,让我们为cmd
使用更复杂的值。
$ cmd="cat /data/test/test.tx* | grep toto"
$ eval '$cmd'
同样,eval
收到文字字符串$cmd
。这是整个命令行,在分词后,所以这是一个简单的命令:没有管道,没有重定向等。参数扩展为单字符串cat /data/test/test.tx* | grep toto
。接下来,单词拆分会生成单词cat
,/data/test/test.tx*
,|
,grep
和toto
。发生路径名扩展
关于模式;我们只是说它扩展为单个文件名/data/test/test.txt
。您现在有5个单词,不再执行扩展,因此shell在命令位置标识单词cat
,并以剩余的4个单词作为参数运行。 cat
无法找到名为|
,grep
和toto
的文件时发生错误。
最后,让我们使用双引号
$ eval "$cmd"
这次,eval
接收扩展字符串cat /data/test/test.tx* | grep toto
作为命令行。分词后,会看到cat
,/data/test/test.tx*
,|
,grep
和toto
。这个多字命令行包含一个管道字符,因此eval
将其作为管道处理。与前面的示例相比,eval
的单个参数只包含一个单词$cmd
。从这里开始,您应该能够看到管道是如何按预期执行的。
总之,如果它是包含您要解析和执行的复杂命令行的单个参数,则需要对eval
的参数使用双引号。
答案 1 :(得分:1)
您需要告诉shell正常处理管道,而不是cat
命令的一部分。一种方法是将它传递给shell的新实例。
sh -c "$cmd"
请注意,这会引入各种引用问题,最好不要尝试将shell元命令存储在变量中。
答案 2 :(得分:0)