如果您的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
通过名称引用了一个变量(并且不包含其他字符),则可以使用${!DEFERRED_EVAL_INC_DIRS}
间接变量引用构造。但是,这是一个更复杂的方案,周围带有文本,并且需要扩展使用变量的多种用途。
我尝试使用bash的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
...,以完全扩展变量DEFERRED_EVAL_INC_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='-I/usr/confused/include -I/usr/confused/local/include' \
./my_command
...,最好在可能的情况下不创建子shell(并且不将该命令分解为多个命令或添加临时变量,这将使情况更简单)。
答案 0 :(得分:1)
您可以在此处使用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
当然要知道使用评估的危险,例如here。
此外,如后续注释中所述,您还可以将“模板”视为要eval
编辑的文件,例如试试这个:
$ 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