【问题标题】:How can I execute a command stored in a variable?如何执行存储在变量中的命令?
【发布时间】:2021-05-14 14:50:42
【问题描述】:

调用存储在变量中的某些命令的正确方法是什么?

1和2有区别吗?

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

#1
$cmd

#2
eval "$cmd"

【问题讨论】:

标签: shell unix parameter-expansion


【解决方案1】:

Unix shell 在执行它们之前对每一行输入进行一系列转换。对于大多数 shell,它看起来像这样(取自 Bash man page):

  • 初始分词
  • 大括号扩展
  • 波浪扩展
  • 参数、变量和算术扩展
  • 命令替换
  • 二次分词
  • 路径扩展(又称通配)
  • 引号删除

在参数扩展阶段直接使用$cmd将其替换为您的命令,然后进行以下所有转换。

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

因此,基本上,它们在大多数情况下是相同的,而当您的命令使用转换步骤直至参数扩展时,它们会有所不同。例如,使用大括号展开:

$ cmd="echo foo{bar,baz}"

$ $cmd
foo{bar,baz}

$ eval "$cmd"
foobar foobaz

【讨论】:

  • 不写eval怎么办eval "$cmd"$($cmd)? ${$cmd}?
  • @StevenLu,没有一个是等价的——故意这样:eval 操作将数据解析为语法;因此,它对安全性非常敏感,并且隐含地这样做是非常糟糕的形式。
【解决方案2】:

如果你只做eval $cmd 而我们做cmd="ls -l"(以交互方式和在脚本中),你会得到想要的结果。在您的情况下,您有一个带有 grep 没有模式的管道,因此 grep 部分将失败并显示错误消息。只需$cmd 就会生成“找不到命令”(或类似的)消息。

所以尝试使用eval(靠近“args 被读取并连接在一起”)并使用完成的命令,而不是生成错误消息的命令。

【讨论】:

  • 只是印刷错误。应该是“grep 异常”。
  • 然后使用 eval,而不是 $cmd 本身,因为它可能不起作用(它在我的测试中没有,在 bash 和 zsh 下)。这就是 eval 的本意……
【解决方案3】:

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

当您想运行不灵活的命令时,第二种方法很有帮助,例如。
for i in {$a..$b}
格式循环不起作用,因为它不允许变量。
在这种情况下,bash 或 eval 的管道是一种解决方法。

在 Mac OSX 10.6.8、Bash 3.2.48 上测试

【讨论】:

    【解决方案4】:

    我觉得你应该放

    `
    

    (反引号)您的变量周围的符号。

    【讨论】:

    • 这会执行命令的输出,例如在 ls -l 的情况下,将生成一条消息,例如“找不到总命令”(因为总 ... 是 ls -l 输出的一部分,例如)所以这不是你想要的。
    猜你喜欢
    • 2017-11-28
    • 2023-03-26
    • 2020-09-10
    • 1970-01-01
    相关资源
    最近更新 更多