我正在尝试编写一个简单的脚本,它将通过标准输入接收文本并按原样输出所有内容,但它将替换遵循以下模式的出现:
{{env MYVAR}}
{{env PATH}}
{{env DISPLAY}}
与环境变量 MYVAR、PATH、DISPLAY 等的内容相关。
我的目标是不向该脚本传递任何参数,因此它将自动检测模式并用环境变量{{env VARNAME}}
的值替换。$VARNAME
该脚本通过标准输入获取输入并通过标准输出提供输出。
通过标准输入的示例输入文本:
This is a basic templating system that can replace environment variables in regular text files.
For example the DISPLAY in this system is {{env DISPLAY}} and the path is {{env PATH}}.
通过标准输出的预期输出:
This is a basic templating system that can replace environment variables in regular text files.
For example the DISPLAY in this system is :0.0 and the path is /bin;/usr/bin;/usr/local/bin.
我已尝试过:
到目前为止,我只设法通过命令行传递一个变量来完成此操作。
#!/bin/sh
# Check if the first argument is set
if [ -z "$1" ]; then
echo "No variable name provided." >&2
exit 1
fi
VARIABLE_NAME="$1"
# Use awk to replace '{{env VARIABLE_NAME}}' with the value of the environment variable
awk -v var_name="$VARIABLE_NAME" '
function escape(s) {
esc = "";
for (i = 1; i <= length(s); i++) {
c = substr(s, i, 1);
if (c ~ /[.[\]$()*+?^{|\\{}]/) {
esc = esc "\\" c;
} else {
esc = esc c;
}
}
return esc;
}
BEGIN {
search = "{{env " var_name "}}";
search_esc = escape(search);
replacement = ENVIRON[var_name];
}
{
gsub(search_esc, replacement);
print;
}'
因此,上述方法有效,但需要你做./parsing_script MYVAR
我想避免将环境变量指定为命令行参数。
架构/操作系统
我正在使用 FreeBSD 的 awk 及其 POSIX shell /bin/sh
笔记
如果 awk 不是合适的工具,我愿意听取解决方案(请不要使用 Python 或 Perl)。
假设:
env
字符串和变量名之间只有一个空格{{env UNDEFINED_VARIABLE}}
字符串示例输入文件:
awk
在尝试替换之前验证环境变量是否存在的一个想法:进行试驾:
这些都产生:
你可以使用这个
awk
解决方案:如果您正在使用
gnu awk
,则可以通过在函数中使用捕获组match
参数进一步简化它:以下内容适用于任何 POSIX
awk
。请注意,它以递归方式执行替换。如果环境变量A={{env B}}
和环境变量B=bar
,则将{{env A}}
替换为bar
。它使用正则表达式,
[{][{]env[[:space:]]+[A-Za-z_][A-Za-z0-9_]*[}][}]
因为有效的 shell 变量名是仅由字母数字字符和下划线组成,并以字母或下划线开头的单词。因此,它不会替换{{env 98FOO}}
。{{env
和变量名之间的空格可以是制表符和空格的任意混合。正如评论中提到的,递归替换可能会导致无限循环(例如
A='{{env A}}'
)。只有一次替换的版本可能类似于:但当然,有了
A='{{env B}}'
和B=bar
,{{env A}}
就会变成{{env B}}
,而不是bar
。输出:
看:
man envsubst
match()
使用 GNU awk将3rg 参数设置为{
在正则表达式的开头或后面不跟数字时的文字:我正在缓慢地填充
tail
,head
而不是不断地重新构造和重新评估,$0
以避免重新评估以前替换的字符串,因此DISPLAY='{{env DISPLAY}}'
不会导致无限循环。我在示例 shell 代码和示例输入中的变量名末尾放置了一个 X,因为我不想弄乱我的真实 DISPLAY 和 PATH。
如果您使用的
{{env FOO}}
不是FOO
环境变量,那么该文本将不会改变。