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
操作将数据解析为语法;因此,它对安全性非常敏感,隐式地这样做将是非常糟糕的形式。