代码之家  ›  专栏  ›  技术社区  ›  Michael Goldshteyn

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

  •  2
  • Michael Goldshteyn  · 技术社区  · 6 年前

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

    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将与其他命令行参数一起执行。

    1 回复  |  直到 6 年前
        1
  •  4
  •   chepner    6 年前

    通常情况下,您不会这样做。在展开参数之前,会识别预命令分配。你必须使用 env 命令:

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

    这样首先展开,然后将结果传递给 埃恩 ,这就创造了必要的环境。然而, 埃恩 期望每个赋值都是单独的参数,这意味着您需要使用数组才能使其正常工作。

    MY_OPT_OPTIONS=(CFLAGS="-O3 -march=native -mtune=native" CPPFLAGS="-O3 -march=native -mtune=native")
    
    env "${MY_OPT_OPTIONS[@]}" gcc ...
    
        2
  •  2
  •   Charles Duffy    6 年前

    使用函数

    除了 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 ...
    

    上述公式产生 埃瓦 -除第一个参数外的所有参数的安全引用,该参数的前缀直接指向 埃瓦 .

    注意,上面使用的“trusted”是nsa安全策略中使用的含义:“trusted”组件是指其故障可能导致整个系统故障的组件。因此,相信事物的本性是不可取的。

    推荐文章