扩展在命令前包含其他变量定义的变量的正确方法是什么?

时间:2019-02-13 15:43:05

标签: bash

具体来说,请考虑以下情况:

MY_OPT_OPTIONS='CFLAGS="-O3 -march=native -mtune=native" CPPFLAGS="-O3 -march=native -mtune=native"'

现在我要使用以下代码执行g ++:

"$MY_OPT_OPTIONS" gcc ...

但这会导致错误:

CFLAGS="-O3: command not found

我想要的是MY_OPT_OPTIONS变量在字面上直接扩展,并让gcc与其他命令行参数一起执行。

2 个答案:

答案 0 :(得分:4)

通常,您不会。在参数扩展之前,可以识别出预命令分配。您将必须使用env命令:

# Wrong, but read on...
env "$MY_OPT_OPTIONS" gcc ...

,以便首先进行扩展,然后将结果传递到env,这将创建必要的环境。但是,env希望将每个分配作为一个单独的参数,这意味着您需要使用一个数组才能使其正常工作。

MY_OPT_OPTIONS=(CFLAGS="-O3 -march=native -mtune=native" CPPFLAGS="-O3 -march=native -mtune=native")

env "${MY_OPT_OPTIONS[@]}" gcc ...

答案 1 :(得分:2)

使用功能

除了chepner's answer与数组一起使用外部命令env之外,另一个选择(仅依赖于shell内置功能)是使用一个函数:

with_my_options() {
  CFLAGS="-O3 -march=native -mtune=native" CPPFLAGS="-O3 -march=native -mtune=native" "$@"
}

with_my_options gcc ...

...之所以有用,是因为"$@"完全按照给定的标准计算出了您的原始命令行。


使用受信任的字符串

如果您真的要使用受信任的,经过审核的字符串,则也可以跳过一堆箍以使用eval,以免产生来自以下方面的安全错误:该字符串以外的内容:

with_trusted_string() {
  local trusted_prefix_str arg_str
  trusted_prefix_str=$1; shift        # store first argument in 'trusted_prefix_str' and pop
  printf -v arg_str '%q ' "$@"        # quote & concatenate remaining arguments into arg_str
  eval "$trusted_prefix_str $arg_str" # evaluate resulting value
}

with_trusted_str "$MY_OPT_OPTIONS" gcc ...

以上公式为除第一个参数外的所有其他参数生成eval-安全引号,该引数直接前缀为馈入eval的字符串。

请注意,以上在NSA安全策略中使用的含义是“受信任”:“受信任”组件是其故障可能导致整个系统发生故障的组件。因此,信任事物本质上是不可取的。