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

多道变量展开,有可能吗?[副本]

  •  0
  • Michael Goldshteyn  · 技术社区  · 7 年前

    如果bash变量包含其他变量,是否可以将其作为命令的一部分“加倍”展开?

    例如:

    # Example #1
    # ----------
    # We define our first variable
    TOP_LEVEL=/usr;
    
    # Then use it (trivially) to set the values of other variables when executing a command
    INC_DIRS="-I$TOP_LEVEL/include -I$TOP_LEVEL/local/include" \
    LIB_DIRS="-L$TOP_LEVEL/lib -L$TOP_LEVEL/local/lib" \
    ./my_command
    

    这是不言而喻的。现在让我们将此示例扩展到问题场景:

    # Example #2
    # ----------
    # We define our first variable
    TOP_LEVEL=/usr;
    
    # Notice the use of single quotes below, to defer expansion of `TOP_LEVEL` to some point
    # later - the time when DEFERRED_EVAL_INC_DIRS will actually be used
    DEFERRED_EVAL_INC_DIRS='-I$TOP_LEVEL/include -I$TOP_LEVEL/local/include'
    ... # Other stuff happens here that may change the value of TOP_LEVEL, e.g.:
    TOP_LEVEL=/usr/confused
    # Since we used single quotes to define DEFERRED_EVAL_INC_DIRS, it is not affected
    
    # Now we want to execute a command like before, and pass it three variables,
    # INC_DIRS, LIB_DIRS, and FOO_LIB_INC_DIRS, in their fully expanded form:
    INC_DIRS="-I$TOP_LEVEL/include -I$TOP_LEVEL/local/include" \
    LIB_DIRS="-L$TOP_LEVEL/lib -L$TOP_LEVEL/local/lib" \
    FOO_LIB_INC_DIRS="$DEFERRED_EVAL_INC_DIRS" ./my_command
    

    扩大 INC_DIRS LIB_DIRS 是微不足道的,它们变成:

    INC_DIRS='-I/usr/confused/include -I/usr/confused/local/include'
    LIB_DIRS='-L/usr/confused/lib -I/usr/confused/local/lib'
    

    有问题的扩展是 FOO_LIB_INC_DIRS 是的。所需的(完全扩展的值应为):

    FOO_LIB_INC_DIRS='-I/usr/confused/include -I/usr/confused/local/include'
    

    …最终扩展了嵌入式 $TOP_LEVEL 值中使用的变量 DEFERRED_EVAL_INC_DIRS 以他们现在的价值 /usr/confused 是的。所以,这个变量需要第二个评估过程,它的值中也有空格需要保留,这只是为了让生活更加困难。

    延期付款公司 按名称引用单个变量(不包含其他字符),则 ${!DEFERRED_EVAL_INC_DIRS} 可以使用间接变量引用构造。但是,这是一个更复杂的场景,包含周围的文本和需要扩展的变量的多个用途。

    我试着玩巴什的 eval ,但无法在一个命令行中实现此扩展,而且不引入其他变量,基本上是作为上面代码段的扩展。完全期望的扩展结果是:

    INC_DIRS='-I/usr/confused/include -I/usr/confused/local/include' \
    LIB_DIRS='-L/usr/confused/lib -I/usr/confused/local/lib' \
    FOO_LIB_INC_DIRS='-I/usr/confused/include -I/usr/confused/local/include' \
    ./my_command
    

    中的命令调用是否可以进行简单的更改或更改集? 例2 为了实现全面扩张?

    更新 :这不是类似问题的重复(至少以任何明显的方式)问题,因为涉及到更复杂的延迟扩展,同时保留了跨空格的单词边界。如果您觉得解决方案很明显,请将其作为答案并更改为:

    INC_DIRS="-I$TOP_LEVEL/include -I$TOP_LEVEL/local/include" \
    LIB_DIRS="-L$TOP_LEVEL/lib -L$TOP_LEVEL/local/lib" \
    FOO_LIB_INC_DIRS="$DEFERRED_EVAL_INC_DIRS" ./my_command
    

    …,以展开变量 延期付款公司 充分尊重单词边界,并产生:

    inc_dirs='-i/usr/confused/include-i/usr/confused/local/include'”\
    lib-dirs='-l/usr/confused/lib-i/usr/confused/local/lib''\
    foo_lib_inc_dirs='-i/usr/confused/include-i/usr/confused/local/include'”\
    /我的命令
    

    …,如果可能的话最好不创建子shell(并且不将此命令分解为多个命令或添加临时变量,这将使情况简单得多)。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Alex Harvey    7 年前

    你可以用 eval 但在这里,当您设置“较低级别”变量时需要调用它,例如,尝试以下操作:

    TOP_LEVEL="/usr"
    eval "INC_DIRS='-I$TOP_LEVEL/include -I$TOP_LEVEL/local/include'"
    echo TOP_LEVEL: $TOP_LEVEL
    echo INC_DIRS: $INC_DIRS
    

    当然也要意识到使用eval的危险。 here 是的。

    此外,如后续注释中所述,您还可以将“模板”视为 评估 Ed,例如,试试这个:

    $ TOP_LEVEL="/usr"
    $ cat template.sh 
    INC_DIRS='-I$TOP_LEVEL/include -I$TOP_LEVEL/local/include'
    $ eval $(<template.sh)
    $ echo $INC_DIRS 
    -I$TOP_LEVEL/include -I$TOP_LEVEL/local/include
    
    推荐文章