Bash HERE文档变量递归解析异常问题排查与解决
Bash HERE文档执行异常问题解答
Q1. 问题根本原因
问题核心在于未加引号的HERE文档的变量展开时机错误:
- 当HERE文档的分隔符(如
EOL)未被单引号包裹时,外层shell会优先展开HERE文档内的所有变量、命令替换,再将内容传递给后续的cat和source操作。 - 第一次执行时,当前shell中还未定义
PATH_JOB、PATH_SRC、PATH_OUT,这些变量在HERE文档展开时被替换为空,导致生成的脚本中echo [$PATH_SRC][$PATH_OUT]被替换为echo [][],执行后输出[][];同时source会将PATH_JOB=$HOME、PATH_SRC=/aaaa、PATH_OUT=/bbbb(因${PATH_JOB}展开为空)导入当前shell。 - 第二次执行时,外层shell会使用当前shell中已有的
PATH_SRC、PATH_OUT值来替换HERE文档内的同名变量,导致输出不符合预期;直到多次执行后,当前shell中的变量值与脚本逻辑生成的值一致,才会输出预期结果。
Q2. 可行解决办法
方法1:给HERE文档分隔符加单引号
通过将分隔符用单引号包裹,让外层shell不处理HERE文档内的变量和命令替换,所有展开逻辑留到source执行时处理:
source <(cat << 'EOL' | tee /tmp/buildvar_eval.sh TODAY=$(date +%y%m%d) PATH_JOB=$HOME PATH_SRC=${PATH_JOB}/aaaa PATH_OUT=${PATH_SRC}/bbbb echo [$PATH_SRC][$PATH_OUT] EOL )
方法2:转义HERE文档内的变量符号
对所有需要延迟展开的$符号添加反斜杠转义,阻止外层shell提前替换:
source <(cat << EOL | tee /tmp/buildvar_eval.sh TODAY=\$(date +%y%m%d) PATH_JOB=\$HOME PATH_SRC=\${PATH_JOB}/aaaa PATH_OUT=\${PATH_SRC}/bbbb echo [\$PATH_SRC][\$PATH_OUT] EOL )
方法3:避免进程替换与HERE文档组合
直接编写临时脚本文件再source,绕开HERE文档的展开问题:
cat > /tmp/buildvar_eval.sh << 'EOL' TODAY=$(date +%y%m%d) PATH_JOB=$HOME PATH_SRC=${PATH_JOB}/aaaa PATH_OUT=${PATH_SRC}/bbbb echo [$PATH_SRC][$PATH_OUT] EOL source /tmp/buildvar_eval.sh
内容的提问来源于stack exchange,提问作者OfusJK
相关产品推荐
相关产品推荐

