bash脚本替换文件中出现的所有占位符

Ant*_*ton 5 linux bash awk sed

我正在尝试编写一个bash脚本,用一个同名环境变量替换文件中所有出现的占位符.举个例子,如果我有一个像下面这样的文件......

This is an {{VAR1}} {{VAR2}}.
It should work across multiple lines in this {{VAR2}}.
Run Code Online (Sandbox Code Playgroud)

...我设置了以下环境变量:

VAR1='example'
VAR2='file'
Run Code Online (Sandbox Code Playgroud)

在我的文件上运行脚本后,我应该得到输出:

This is an example file.
It should work across multiple lines in this file.
Run Code Online (Sandbox Code Playgroud)

我确定必须有一个使用awk/sed的解决方案,但到目前为止,如果一条线路上有多个变量,我最接近的就无法处理.这是我到目前为止的尝试:

cat example.txt | grep -o '{{.*}}' > temp
while read placeholder; do
  varName=$(echo "$placeholder" | tr -d '{}')
  value="${!varName}"
  sed -i "s/$placeholder/$value/g" "$file"
done < temp
rm -rf temp
Run Code Online (Sandbox Code Playgroud)

Win*_*ute 7

我用Perl:

perl -pe 's/{{(.*?)}}/$ENV{$1}/g' filename
Run Code Online (Sandbox Code Playgroud)

这假设VAR1VAR2是环境变量(即exported),以便Perl可以从环境中选择它们.任何非纯壳的方法都需要这样做; 我只是提到它以避免混淆.

其工作原理如下:

  • s/pattern/replacement/g是一个替代命令; 你可以从sed认出来.不同之处在于,我们可以使用Perl更强大的正则表达式引擎和变量.该g标志使得所有匹配都被替换; 没有它,它只适用于第一个.
  • 在模式中,.*?非贪婪地匹配,因此在包含的行中foo {{VAR1}} bar {{VAR2}} baz,模式{{.*?}}仅匹配{{VAR1}}而不是{{VAR1}} bar {{VAR2}}.
  • 之间{{和之间的部分}}被捕获,因为它介于两者之间(),可以重复使用$1
  • $ENV{$1}在替换中使用%ENV包含Perl进程环境的特殊哈希.$ENV{$1}是具有名称的环境变量的值,该名称$1是之前捕获的组.