【发布时间】:2021-05-14 14:50:42
【问题描述】:
调用存储在变量中的某些命令的正确方法是什么?
1和2有区别吗?
#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
【问题讨论】:
-
请看BashFAQ/050。
标签: shell unix parameter-expansion
调用存储在变量中的某些命令的正确方法是什么?
1和2有区别吗?
#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
【问题讨论】:
标签: shell unix parameter-expansion
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}?
eval 操作将数据解析为语法;因此,它对安全性非常敏感,并且隐含地这样做是非常糟糕的形式。
如果你只做eval $cmd 而我们做cmd="ls -l"(以交互方式和在脚本中),你会得到想要的结果。在您的情况下,您有一个带有 grep 没有模式的管道,因此 grep 部分将失败并显示错误消息。只需$cmd 就会生成“找不到命令”(或类似的)消息。
所以尝试使用eval(靠近“args 被读取并连接在一起”)并使用完成的命令,而不是生成错误消息的命令。
【讨论】:
$cmd 只会将变量替换为要在命令行上执行的值。
eval "$cmd" 在命令行上执行结果值之前进行变量扩展和命令替换
当您想运行不灵活的命令时,第二种方法很有帮助,例如。
for i in {$a..$b}
格式循环不起作用,因为它不允许变量。
在这种情况下,bash 或 eval 的管道是一种解决方法。
在 Mac OSX 10.6.8、Bash 3.2.48 上测试
【讨论】:
我觉得你应该放
`
(反引号)您的变量周围的符号。
【讨论】: