调用存储在变量中的某个命令的正确方法是什么?
1和2之间有什么区别吗?
#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
答案 0 :(得分:84)
Unix shell在执行它们之前对每行输入操作一系列转换。对于大多数shell,它看起来像这样(取自bash
联机帮助页):
在参数扩展阶段,直接使用$cmd
将其替换为您的命令,然后进行所有后续转换。
使用eval "$cmd"
除了引用删除阶段之外什么都不做,其中$cmd
按原样返回,并作为参数传递给eval
,其功能是再次运行整个链执行。
基本上,它们在大多数情况下都是相同的,并且当您的命令使用转换步骤直到参数扩展时,它们会有所不同。例如,使用大括号扩展:
$ cmd="echo foo{bar,baz}"
$ $cmd
foo{bar,baz}
$ eval "$cmd"
foobar foobaz
答案 1 :(得分:5)
如果您这样做eval $cmd
当我们cmd="ls -l"
(交互式地并且在脚本中)时,我们得到了期望的结果。在您的情况下,您有一个没有模式的grep管道,因此grep部分将失败并显示错误消息。只有$cmd
才会生成“未找到命令”(或某些此类消息)。
因此,请尝试使用eval并使用完成的命令,而不是生成错误消息的命令。
答案 2 :(得分:0)
$cmd
只是将变量替换为其要在命令行上执行的值。
eval "$cmd"
在命令行上执行结果值之前先进行变量扩展和命令替换
当您想运行不灵活的命令时,第二种方法很有用。
for i in {$a..$b}
format循环不起作用,因为它不允许变量。
在这种情况下,bash或eval的管道是一种解决方法。
在Mac OSX 10.6.8,Bash 3.2.48上进行了测试
答案 3 :(得分:-4)
我认为你应该把
`
变量周围的(反引号)符号。