在另一个变量中替换 shell 变量名

MLu*_*MLu 1 bash variable-substitution

我一直在与bash变量替换搏斗一段时间,但无法弄清楚这一点......

我有一个带有命令模板的变量:

CMD_TMPL='sudo -u ${USER_NAME} ${USER_HOME}/script.sh'
Run Code Online (Sandbox Code Playgroud)

变量USER_NAMEUSER_HOME稍后在脚本中计算出来,当时还不知道CMD_TMPL被定义。因此该命令是单引号并且尚未被替换。

然后脚本弄清楚了USER_NAME=testUSER_HOME=/home/test我想做一些会导致${CMD}包含的事情:

sudo -u test /home/test/script.sh
Run Code Online (Sandbox Code Playgroud)

在脚本的进一步下方,我将在管道中使用该命令,例如:

${CMD} | output-processing.sh
Run Code Online (Sandbox Code Playgroud)

如何实现从变量名${CMD_TMPL}到变量值的扩展${CMD}?我尝试了各种echo's 和eval's 但无法弄清楚。

谢谢!

Sté*_*las 6

有一种特殊类型的变量用于存储代码,即函数

cmd_tmpl() { sudo -u "$USER_NAME" "$USER_HOME/script.sh" "$@"; }
cmd() { cmd_tmpl other args "$@"; }
cmd | output_processing...
Run Code Online (Sandbox Code Playgroud)

其他方法是将变量视为命令行(shell 代码),并最终使用eval以下方法解释该代码:

cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"'
cmd=$cmd_tmpl' other args as shell code'
eval "$cmd" | output_processing...
Run Code Online (Sandbox Code Playgroud)

使用$cmd | output_processing是错误的。$cmd是一个标量变量,并且您使用 split+glob 运算符来获取简单命令的参数列表,而不是评估存储在其中的命令行。所以这只适用于一组受限制的条件。

您可以将一个简单命令的参数存储在一个数组中:

cmd=(sudo -u "$USER_NAME" "$USER_HOME/script.sh" ...)
"${cmd[@]}" | post_processing
Run Code Online (Sandbox Code Playgroud)

但这无助于您的变量的延迟扩展。

您可以通过以下方式推迟扩展:

cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"'
...
eval "cmd=($cmd_tmpl)" # now expanded
cmd+=(other args)
"${cmd[@]}" | post-processing
Run Code Online (Sandbox Code Playgroud)

(请注意,为导出到环境的变量保留全大写的变量名称是一种很好的做法)。