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

时间:2015-04-28 12:36:22

标签: linux bash awk sed

我试图编写一个bash脚本,用一个同名环境变量替换文件中所有出现的占位符。例如,如果我有一个类似以下的文件......

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

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

VAR1='example'
VAR2='file'

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

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

我确定必须有一个使用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

3 个答案:

答案 0 :(得分:5)

我使用Perl:

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

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

其工作原理如下:

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

答案 1 :(得分:1)

bashsed

$ VAR1='example'
$ VAR2='file'
$ export VAR1 VAR2

$ sed -e '{s/{{\([^{]*\)}}/${\1}/g; s/^/echo "/; s/$/";/}' -e e 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

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

答案 2 :(得分:1)

我只是玩你原来的方法。不会在$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