Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 替换文件中所有出现的占位符的bash脚本_Linux_Bash_Awk_Sed - Fatal编程技术网

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

Linux 替换文件中所有出现的占位符的bash脚本,linux,bash,awk,sed,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 wor

我正在尝试编写一个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
cat example.txt | grep-o'{{.*}>temp
读占位符时;做
varName=$(echo“$placeholder”| tr-d'{}')
value=“${!varName}”
sed-i“s/$placeholder/$value/g”“$file”
完成<温度
rm-射频温度
我会使用Perl:

perl -pe 's/{{(.*?)}}/$ENV{$1}/g' filename
这假设
VAR1
VAR2
是环境变量(即
export
ed),因此Perl可以从其环境中选择它们。这对于任何非纯shell的方法都是必需的;我只是提一下以避免混淆

这项工作如下:

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

bash
sed

$ 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;}'文件名

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

    This is an ${VAR1} ${VAR2}.
    It should work across multiple lines in this ${VAR2}.
    
    echo "This is an ${VAR1} ${VAR2}.";
    echo "It should work across multiple lines in this ${VAR2}.";
    
    • s/^/echo”/
      -将行的开头替换为
      echo“
    • 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
cat example.txt | grep-o'{{.*}>temp
读占位符时;执行
varName=$(echo“$placeholder”| tr-d'{}')
因为我用$varName;做
value=“${!i}”
sed-i“s/{{$i}}/$value/g”example.txt
完成
完成<温度
rm-射频温度

你考虑过使用
m4
宏处理器吗?@MarkSetchell我没听说过m4,但我会去看看。谢谢。这太棒了-正是我想要的!谢谢@Wintermute!在运行此操作之前,确保在脚本中导出VAR1 VAR2,否则它将无法工作。