强制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

许多使用evalechotypes的工作的答案,但打破了各种各样的东西,如多行,试图逃脱壳元字符,在模板内逃脱不打算由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