Shell 如何执行存储在变量中的命令?

Shell 如何执行存储在变量中的命令?,shell,unix,parameter-expansion,Shell,Unix,Parameter Expansion,调用存储在变量中的某个命令的正确方法是什么? 1和2之间有什么区别吗 #!/bin/sh cmd="ls -la $APPROOTDIR | grep exception" #1 $cmd #2 eval "$cmd" 我想你应该把 ` (反勾选)变量周围的符号。如果您只是执行eval$cmd 当我们执行cmd=“ls-l”(以交互方式和脚本形式)时,我们会得到所需的结果。在您的例子中,您有一个带有grep但没有模式的管道,因此grep部分将失败并显示错误消息。只要$cmd就会生成一条“未找

调用存储在变量中的某个命令的正确方法是什么?
1和2之间有什么区别吗

#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"

我想你应该把

`

(反勾选)变量周围的符号。

如果您只是执行
eval$cmd
当我们执行
cmd=“ls-l”
(以交互方式和脚本形式)时,我们会得到所需的结果。在您的例子中,您有一个带有grep但没有模式的管道,因此grep部分将失败并显示错误消息。只要
$cmd
就会生成一条“未找到命令”(或类似的)消息。
因此,请尝试使用eval并使用已完成的命令,而不是生成错误消息的命令。

unixshell在执行前对每行输入操作一系列转换。对于大多数shell,它看起来像这样(取自
bash
manpage):

  • 初始分词
  • 支架扩张
  • 瓷砖膨胀
  • 参数、变量和算术展开
  • 命令替换
  • 二次分词
  • 路径扩展(又名globbing)
  • 删除报价
在参数扩展阶段,使用
$cmd
直接将其替换为您的命令,然后它将经历以下所有转换

使用
eval“$cmd”
不会执行任何操作,直到报价删除阶段,
$cmd
按原样返回,并作为参数传递给
eval
,其功能是在执行之前再次运行整个链

所以基本上,它们在大多数情况下是相同的,当您的命令使用转换步骤进行参数扩展时,它们是不同的。例如,使用支撑展开:

$ cmd="echo foo{bar,baz}"
$ $cmd
foo{bar,baz}
$ eval "$cmd"
foobar foobaz

$cmd
只是将变量替换为要在命令行上执行的值。
eval“$cmd”
在命令行上执行结果值之前执行变量扩展和命令替换

第二种方法在您想要运行不灵活的命令时很有用,例如。
对于{$a..$b}中的i

格式循环将不起作用,因为它不允许变量
在这种情况下,bash或eval的管道是一种解决方法


在Mac OSX 10.6.8上测试,Bash 3.2.48执行命令的输出,例如在ls-l的情况下,将生成一条类似“total”的消息command not found(因为total…是ls-l输出的一部分,例如),因此这不是您想要的。这只是打印错误。应该是“grep exception”“。然后使用eval,而不是$cmd本身,因为它可能不起作用(在我的测试中,在bash和zsh下没有)。这就是eval要做的…请参阅。如何在不写
eval
的情况下执行
eval“$cmd”
<代码>$($cmd)
${$cmd}
?@StevenLu,这些都不是等价的——故意这样:一个
eval
操作将数据解析为语法;因此,它对安全性非常敏感,隐式地这样做将是非常糟糕的形式。