我已经在bash
变量替换上苦苦挣扎了一段时间,但无法弄清楚这一点......
我有一个带有命令模板的变量:
CMD_TMPL='sudo -u ${USER_NAME} ${USER_HOME}/script.sh'
变量USER_NAME
和USER_HOME
是稍后在脚本中计算出来的,当时还不知道CMD_TMPL
被定义。因此该命令用单引号括起来并且尚未被替换。
然后脚本就明白了USER_NAME=test
,USER_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
(请注意,最好将全大写变量名称保留给导出到环境的变量)。