MLu*_*MLu 1 bash variable-substitution
我一直在与bash
变量替换搏斗一段时间,但无法弄清楚这一点......
我有一个带有命令模板的变量:
CMD_TMPL='sudo -u ${USER_NAME} ${USER_HOME}/script.sh'
Run Code Online (Sandbox Code Playgroud)
变量USER_NAME
和USER_HOME
稍后在脚本中计算出来,当时还不知道CMD_TMPL
被定义。因此该命令是单引号并且尚未被替换。
然后脚本弄清楚了USER_NAME=test
,USER_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 但无法弄清楚。
谢谢!
有一种特殊类型的变量用于存储代码,即函数:
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)
(请注意,为导出到环境的变量保留全大写的变量名称是一种很好的做法)。