【问题标题】:bash script to replace all occurrences of placeholders in filebash脚本替换文件中所有出现的占位符
【发布时间】:2015-04-28 23:19:32
【问题描述】:

我正在尝试编写一个 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

【问题讨论】:

  • 您考虑过使用m4 宏处理器吗?
  • @MarkSetchell 我没听说过 m4,但我会去看看。谢谢。

标签: linux bash awk sed


【解决方案1】:

我会使用 Perl:

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

这假定VAR1VAR2 是环境变量(即是exported),因此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 的环境变量的值,它是之前捕获的组。

【讨论】:

  • 这太棒了——正是我想要的!谢谢@Wintermute!
  • 在运行这个之前确保你在你的脚本中export VAR1 VAR2,否则它将不起作用。
【解决方案2】:

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/$/";/ - 将行尾替换为 ";

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2014-05-24
      • 2021-08-21
      • 2021-08-22
      • 1970-01-01
      • 1970-01-01
      • 2019-12-20
      • 1970-01-01
      • 2010-09-29
      相关资源
      最近更新 更多