与评估变量相比,eval / bash -c的重点是什么?

时间:2015-12-23 01:22:24

标签: linux bash shell unix sh

假设您将以下命令存储在变量中:

COMMAND='echo hello'

之间的区别是什么
$ eval "$COMMAND"
hello

$ bash -c "$COMMAND"
hello

$ $COMMAND
hello

?为什么最后一个版本几乎从不使用,如果它更短并且(据我所知)完全相同的事情?

3 个答案:

答案 0 :(得分:11)

第三种形式与其他两种形式完全不同 - 但要理解为什么,我们需要在解释命令时按bash进行操作的顺序,并查看每种方法进入时遵循哪些操作使用

Bash Parsing Stages

  1. 报价处理
  2. 分裂为命令
  3. 特殊操作员解析
  4. 展开
  5. Word Splitting
  6. 通配
  7. 执行
  8. 使用eval "$string"

    eval "$string"遵循从#1开始的所有上述步骤。因此:

    • 字符串中的字面引号成为语法引号
    • 处理>()等特殊操作符
    • 尊重$foo等扩展
    • 这些扩展的结果在字符上分成空格分成单词
    • 如果这些单词解析为相同且具有可用匹配项,那么这些单词将被展开为globs,最后执行该命令。

    使用sh -c "$string"

    ...执行与eval相同,但在作为单独进程启动的新shell中;因此,当这个新进程退出时,对变量状态,当前目录等的更改将到期。 (另请注意,新shell可能是支持不同语言的不同解释器;即。sh -c "foo"将不支持bashkshzsh的相同语法等等。)。

    使用$string

    ...从第5步开始,“Word Splitting”。

    这是什么意思?

    行情不尊重。

    因此,{p> printf '%s\n' "two words"将解析为printf %s\n "two words",而不是printf {{1}的通常/预期行为} %s\n(shell引用了引号)。

    不会分割成多个命令(two words;或类似命令)。

    因此:

    &

    ...将发出以下输出:

    s='echo foo && echo bar'
    $s
    

    ...而不是以下,否则将是预期的:

    foo && echo bar
    

    不尊重特殊运营商和扩展。

    不是foo bar ,没有$(foo),没有$foo等等。

    重定向不受尊重。

    <(foo)>foo只是字符串拆分创建的另一个单词,而不是shell指令。

答案 1 :(得分:1)

至少有些时候它们不同。请考虑以下事项:

$ cmd="echo \$var"
$ var=hello
$ $cmd
$var
$ eval $cmd
hello
$ bash -c "$cmd"

$ var=world bash -c "$cmd"
world

显示执行变量扩展的不同点。如果我们先set -x

,那就更清楚了
$ set -x
$ $cmd
+ echo '$var'
$var
$ eval $cmd
+ eval echo '$var'
++ echo hello
hello
$ bash -c "$cmd"
+ bash -c 'echo $var'

$ var=world bash -c "$cmd"
+ var=world
+ bash -c 'echo $var'
world

我们可以在这里看到查尔斯达菲在他的出色答案中谈到的很多内容。例如,尝试执行变量会直接打印$var,因为参数扩展和前面的步骤已经完成,所以我们没有像{{1}那样得到var的值}}

eval选项仅从父shell继承bash -c ed变量,因为我没有导出export,所以它不适用于新shell。

答案 2 :(得分:1)

$ bash -c "$COMMAND"

此版本启动一个新的bash解释器,运行命令,然后退出,将控制权返回给原始shell。你不需要首先运行bash来做到这一点,你可以从tcsh开始一个bash解释器,例如。您也可以从bash脚本执行此操作,以从新环境开始,或者避免污染当前环境。

修改

正如@CharlesDuffy指出以这种方式启动一个新的bash shell将清除shell变量,但环境变量将由生成的shell进程继承。

使用eval会导致shell解析您的命令两次。在您提供的示例中,直接执行$ COMMAND或执行eval是等效的,但请查看答案here以更全面地了解eval的优点(或坏的)。