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

Vol*_*lyy 78 unix shell parameter-expansion

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

#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
Run Code Online (Sandbox Code Playgroud)

JB.*_*JB. 89

Unix shell在执行它们之前对每行输入操作一系列转换.对于大多数shell,它看起来像这样(取自手册bash页):

  • 最初的单词分裂
  • 支撑扩张
  • 波浪扩张
  • 参数,变量和算术扩展
  • 命令替换
  • 次要词分裂
  • 路径扩展(aka globbing)
  • 报价删除

$cmd在参数扩展阶段,使用直接使用命令替换它,然后进行所有后续转换.

eval "$cmd"在报价删除阶段之前,使用什么都不做,其中$cmd按原样返回,并作为参数传递给eval,其功能是在执行之前再次运行整个链.

所以基本上,它们在大多数情况下是相同的,并且当您的命令使用转换步骤直到参数扩展时,它们会有所不同.例如,使用大括号扩展:

$ cmd="echo foo{bar,baz}"
$ $cmd
foo{bar,baz}
$ eval "$cmd"
foobar foobaz
Run Code Online (Sandbox Code Playgroud)

  • 如何做'eval'$ cmd"`而不写'eval`?`$($ CMD)`?`$ {$ CMD}`? (5认同)
  • @StevenLu,没有一个是等价的 - 故意这样:`eval`操作将数据解析为语法; 因此它对安全性非常敏感,并且隐含地执行它将是非常糟糕的形式. (2认同)

Hen*_*sma 5

如果你只是eval $cmd 在我们做的时候cmd="ls -l"(交互式地和在脚本中)我们得到了期望的结果.在您的情况下,您有一个没有模式的grep管道,因此grep部分将失败并显示错误消息.只需$cmd将产生一个"命令未找到"(或类似)的消息.因此,请尝试使用eval并使用完成的命令,而不是生成错误消息的命令.