2013-08-23 35 views
0

如果我救我的猫命令转换成字符串,然后我执行它,然后我会得到一个错误

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

在/ data/test中是否有test.tx *? – fedorqui

+0

@fedorqui是的,有test.txt文件 – MOHAMED

+0

'eval'应该在这里工作。 – devnull

回答

4

让我们先从一个简单的命令,无论哪种方式,但由于不同的原因。

$ cmd="echo anymessage" 
$ eval '$cmd' 

eval '$cmd'具有eval处理字符串$cmd。它将它分解成单词,这又是单个单词$cmd。它将参数扩展为echo anymessage并执行一轮的分词,得到echoanymessage。现在,echo是命令,anymessage是参数,并且执行了echo命令。

$ eval "$cmd" 

这里,eval正在处理串echo anymessage,因为bash已执行eval之前进行上$cmd参数扩展。该字符串再次被分成单词,并且将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*,|, greptoto。在模式上发生路径名扩展 ;我们只是说它扩展到单个文件名/data/test/test.txt。您现在有5个单词,没有更多的扩展可执行,因此shell会在命令位置标识单词cat,并以剩余的4个单词作为参数运行该单词。 cat无法找到名为|greptoto的文件时发生该错误。

最后,让我们用双引号

$ eval "$cmd" 

这一次,eval接收扩展字符串cat /data/test/test.tx* | grep toto作为命令行。分词后,它看到cat,/data/test/test.tx*,|,greptoto。这个多字命令行包含一个管道字符,因此eval将其作为管道进行处理。与前面的例子相比,eval的单参数只包含一个单词$cmd。从这里,你应该能够看到管道是如何按预期执行的。


总之,您需要在参数中使用双引号eval是否为包含要解析和执行复杂的命令行的参数。

1

你需要告诉shell正常处理管道,还不如cat命令的一部分。一种方法是将它传递给shell的新实例。

sh -c "$cmd" 

请注意,这会引入各种引用问题,最好不要尝试将shell metacommands存储在变量中。

+0

对不起,我在我的问题中犯了一个错误。我更新了。事实上,“eval”$ cmd“'作品 – MOHAMED

+0

仍然不会将您从引用问题中拯救出来。 –

0

另请注意,如果文件夹中没有文件,此代码将失败。这是将要抛出的错误:

猫:*:没有这样的文件或目录

为了解决这个问题,你可以启用nullglob

shopt -s nullglob