hello $FOO world
我接着运行
export FOO=42
echo $(cat something.txt)
这将返回: hello $FOO world
尽管设置了变量,它没有扩展$FOO。我无法评估或源化该文件 - 因为它将尝试执行它(它不可执行 - 我只想要带有插值变量的字符串)。
有什么想法吗?
我偶然发现了我认为是这个问题的答案: envsubst
命令:
echo "hello \$FOO world" > source.txt
export FOO=42
envsubst < source.txt
这将输出:hello 42 world
如果您想继续在名为destination.txt
的文件中处理数据,请按如下方式将其推回文件:
envsubst < source.txt > destination.txt
gettext
中。@Rockallite
(顺便说一句,envsubst有一个“特性”,在https://unix.stackexchange.com/a/294400/7088上有解释,可以只扩展输入中的某些变量,但是我同意转义异常更方便。)
这是我的脚本:
#! /bin/bash
## -*-Shell-Script-*-
CmdName=${0##*/}
Usage="usage: $CmdName runs envsubst, but allows '\$' to keep variables from
being expanded.
With option -sl '\$' keeps the back-slash.
Default is to replace '\$' with '$'
"
if [[ $1 = -h ]] ;then echo -e >&2 "$Usage" ; exit 1 ;fi
if [[ $1 = -sl ]] ;then sl='\' ; shift ;fi
sed 's/\\\$/\${EnVsUbDolR}/g' | EnVsUbDolR=$sl\$ envsubst "$@"
$
)转义,例如 echo '\$USER' | envsubst
将输出带有前缀反斜杠的当前用户名,而不是 $USER
。 - Rockallitebrew link --force gettext
。 - KeepCalmAndCarryOn很多使用 eval
和 echo
的答案都有一定的效果,但会因为各种原因而出错,例如多行、尝试转义shell元字符、模板中不打算被bash扩展的转义等。
我也曾遇到同样的问题,并编写了这个Shell函数,据我所知,它可以正确处理所有情况。由于bash的命令替换规则,这个函数仍将仅从模板中去除末尾的换行符,但只要其他所有内容保持完整,我从未发现这是个问题。
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
的脚本文件设置变量,以及使用这些变量的模板template.txt
:. parameters.cfg
printf "%s\n" "$(apply_shell_expansion template.txt)" > result.txt
在实践中,我将其用作一种轻量级模板系统。
; $(eval date)
,它将运行date
命令。 - anubhava你可以尝试
echo $(eval echo $(cat something.txt))
echo -e "$(eval "echo -e \"\
<something.txt`"")"`。 - peviktemplate.txt
是文本时才可以这样做。这个操作很危险,因为它会执行(评估)命令。 - kyb您不想打印每一行,而是想对其进行评估,以便Bash可以执行变量替换。
FOO=42
while read; do
eval echo "$REPLY"
done < something.txt
请参考help eval
或Bash手册获取更多信息。
something=$(cat something.txt)
echo "echo \"" > temp.out
echo "$something" >> temp.out
echo "\"" >> temp.out
然后将其源代码返回到一个变量中:
RESULT=$(source temp.out)
使用单行解决方案而不需要临时文件:
并且$RESULT将会展开所有内容。但是这样做似乎不太正确!
只需一行解决方案即可,无需临时文件:
RESULT=$(source <(echo "echo \"$(cat something.txt)\""))
#or
RESULT=$(source <(echo "echo \"$(<something.txt)\""))
eval
的答案一样危险,因为它暗示了隐式的eval
。试试echo '$(rm -rf /)' > something.txt
,然后再尝试你的解决方案... - undefinedcontents="$(cat something.txt)"
echo $(eval echo \"$contents\")
eval "echo \"$$contents\""
,这样可以保留空格。 - khusseinieval "echo \"$contents\""
?$$contents
是脚本的进程ID,后面跟着单词contents
。 - Soren Bjornstadeval
的答案一样危险。试试echo '$(rm -rf /)' > something.txt
,然后再试试你的解决方案... - undefinedIf something.txt has only one line, a bash
method, (a shorter version of Michael Neale's "icky" answer),
using process & command substitution:
FOO=42 . <(echo -e echo $(<something.txt))
Output:
hello 42 world
Note that export
isn't needed.
If something.txt has one or more lines, a GNU sed
e
valuate method:
FOO=42 sed 's/"/\\\"/g;s/.*/echo "&"/e' something.txt
sed
最适合我的目的。我需要从模板生成脚本,这些脚本将从另一个配置文件中导出的变量填充值。它可以正确处理命令扩展的转义,例如在模板中放置\$(date)
以获取输出中的$(date)
。谢谢! - gadamiakeval
的答案一样危险,因为它暗示了一个隐式的eval
。试试echo '$(rm -rf /)' > something.txt
,然后再尝试你的解决方案... - undefinedfoo=45
file=something.txt # in a file is written: Hello $foo world!
eval echo $(cat $file)
eval
的答案一样危险。试试echo '$(rm -rf /)' > something.txt
,然后再尝试你的解决方案... - undefined以下是解决方案:
允许替换已定义的变量
保留未定义变量的占位符不变。这在自动化部署中非常有用。
支持以下格式的变量替换:
${var_NAME}
$var_NAME
报告环境中未定义的变量,并为此类情况返回错误代码。
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
$ eval echo $(cat something.txt)
hello 42 world
$ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin17)
Copyright (C) 2007 Free Software Foundation, Inc.
eval
的答案一样危险。试试echo '$(rm -rf /)' > something.txt
,然后再看你的解决方案…… - undefined
eval
的安全隐患。参考链接:http://mywiki.wooledge.org/BashFAQ/048。 - Dennis Williamsoneval
,了解其潜在影响非常重要。 - Dennis Williamson