bash脚本来replace文件中的所有占位符

我试图编写一个bash脚本来replace文件中所有出现的占位符与同名的环境variables。 作为一个例子,如果我有像下面这样的文件…

This is an {{VAR1}} {{VAR2}}. It should work across multiple lines in this {{VAR2}}. 

…我有以下的环境variables设置:

 VAR1='example' VAR2='file' 

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

 This is an example file. It should work across multiple lines in this file. 

我确定使用awk / sed必须有一个解决scheme,但是到目前为止,如果一行中有多个variables,那么最近我不能处理。 这是我迄今为止的尝试:

 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 

我会使用Perl:

 perl -pe 's/{{(.*?)}}/$ENV{$1}/g' filename 

这假设VAR1VAR2是环境变量(即export ),以便Perl可以将它们从环境中挑选出来。 这将是任何不是纯粹的方法的要求, 我只是提到它以避免混淆。

这工作如下:

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

只有bashsed

 $ VAR1='example' $ VAR2='file' $ export VAR1 VAR2 $ sed -e '{s/{{\([^{]*\)}}/${\1}/g; s/^/echo "/; s/$/";/}' -ee filename This is an example file. It should work across multiple lines in this file. 
  • sed -e '{s/{{\([^{]*\)}}/${\1}/g;}' filename

     This is an ${VAR1} ${VAR2}. It should work across multiple lines in this ${VAR2}. 
    • {{\([^{]*\)}} – 搜索{{..}}
    • [^{] – 非贪婪的匹配
    • \1 – 访问括号内的值\(...\)
  • sed -e '{s/{{\([^{]*\)}}/${\1}/g; s/^/echo "/; s/$/";/}' filename sed -e '{s/{{\([^{]*\)}}/${\1}/g; s/^/echo "/; s/$/";/}' filename

     echo "This is an ${VAR1} ${VAR2}."; echo "It should work across multiple lines in this ${VAR2}."; 
    • s/^/echo "/ – 用s/^/echo "/替换行的开头echo "
    • s/$/";/ – 用s/$/";/替换行的结尾";

我只是在玩你原来的方法。 $varName工作不会添加另一个循环?

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