替换另一个变量中的 shell 变量名称

替换另一个变量中的 shell 变量名称

我已经在bash变量替换上苦苦挣扎了一段时间,但无法弄清楚这一点......

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

CMD_TMPL='sudo -u ${USER_NAME} ${USER_HOME}/script.sh'

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

然后脚本就明白了USER_NAME=testUSER_HOME=/home/test我想做一些事情来${CMD}包含:

sudo -u test /home/test/script.sh

在脚本的下面,我将在管道中使用该命令,例如:

${CMD} | output-processing.sh

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

谢谢!

答案1

有一种特殊类型的变量用于存储代码,那就是功能:

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

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

cmd_tmpl='sudo -u "$USER_NAME" "$USER_HOME/script.sh"'
cmd=$cmd_tmpl' other args as shell code'
eval "$cmd" | output_processing...

使用$cmd | output_processing是错误的。$cmd是一个标量变量,并且您使用 split+glob 运算符来获取简单命令的参数列表,您不会评估存储在其中的命令行。因此,这仅在一组受限条件下有效。

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

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

但这对变量的延迟扩展没有帮助。

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

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

(请注意,最好将全大写变量名称保留给导出到环境的变量)。

相关内容