强制bash扩展从文件加载的string中的variables
我正在试图找出如何使bash(强制?)在一个string(从文件加载)中展开variables。
我有一个名为“something.txt”的文件的内容:
hello $FOO world
然后我跑
export FOO=42 echo $(cat something.txt)
这返回:
hello $FOO world
即使设置了variables,它也不会扩展$ FOO。 我无法评估或源文件 – 因为它会尝试和执行它(它不是可执行的,因为它 – 我只是想插入variables的string)。
有任何想法吗?
我偶然发现我认为是这个问题的答案: envsubst
命令。
envsubst < something.txt
如果你的发行版本中还没有这个function,那么就在GNU软件包gettext
。
许多使用eval
和echo
types的工作的答案,但打破了各种各样的东西,如多行,试图逃脱壳元字符,在模板内逃脱不打算由bash扩展,等等。
我有同样的问题,并写了这个shell函数,据我所知,正确处理一切。 由于bash的命令replace规则,这仍然会剥离模板中的尾随换行符,但是只要其他所有内容都保持不变,我从来没有发现这是一个问题。
apply_shell_expansion() { declare file="$1" declare data=$(< "$file") declare delimiter="__apply_shell_expansion_delimiter__" declare command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter" eval "$command" }
例如,你可以像这样使用它,它的parameters.cfg
是一个真正的shell脚本,它只是设置variables,而template.txt
是一个使用这些variables的模板:
. parameters.cfg printf "%s\n" "$(apply_shell_expansion template.txt)" > result.txt
在实践中,我将其用作一种轻量级模板系统。
你可以试试
echo $(eval echo $(cat something.txt))
你不想打印每一行,你想评估它,以便Bash可以执行variablesreplace。
FOO=42 while read; do eval echo "$REPLY" done < something.txt
请参阅help eval
或Bash手册了解更多信息。
另一种方法(这似乎是icky,但是我把它放在这里):
将something.txt的内容写入一个临时文件,并用echo语句包装它:
something=$(cat something.txt) echo "echo \"" > temp.out echo "$something" >> temp.out echo "\"" >> temp.out
然后将其恢复到一个variables:
RESULT=$(source temp.out)
$ RESULT将会扩展。 但是这似乎是错的!
如果你只想要扩展variables引用(我自己有一个目标),你可以做下面的事情。
contents="$(cat something.txt)" echo $(eval echo \"$contents\")
(关于$内容的转义引号是关键)
解决scheme如下
-
允许replace定义的variables
-
保留未定义的variables占位符。 这在自动部署期间特别有用。
-
支持以下格式的variablesreplace:
${var_NAME}
$var_NAME
-
报告哪些variables没有在环境中定义,并返回这种情况下的错误代码
TARGET_FILE=someFile.txt; ERR_CNT=0; for VARNAME in $(grep -P -o -e '\$[\{]?(\w+)*[\}]?' ${TARGET_FILE} | sort -u); do VAR_VALUE=${!VARNAME}; VARNAME2=$(echo $VARNAME| sed -e 's|^\${||g' -e 's|}$||g' -e 's|^\$||g' ); VAR_VALUE2=${!VARNAME2}; if [ "xxx" = "xxx$VAR_VALUE2" ]; then echo "$VARNAME is undefined "; ERR_CNT=$((ERR_CNT+1)); else echo "replacing $VARNAME with $VAR_VALUE2" ; sed -i "s|$VARNAME|$VAR_VALUE2|g" ${TARGET_FILE}; fi done if [ ${ERR_CNT} -gt 0 ]; then echo "Found $ERR_CNT undefined environment variables"; exit 1 fi