【问题标题】:perl Multiline Find and Replace with regexperl 使用正则表达式进行多行查找和替换
【发布时间】:2016-10-05 21:36:37
【问题描述】:

我有一个属性文件test.properties,其中包含如下所示的一些内容:

#DEV
#jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
#ems_value=emsdev.example

我想根据文件所在的环境取消环境名下的注释。

如果文件进入 DEV 环境。我需要取消注释所有“#DEV”下的行。我使用了以下命令:

perl -i -p -e 's/#DEV\n#(.*)/#DEV\n\1/g;' test.properties

这不会改变文件中的任何内容。

谁能帮我找到解决方案?

【问题讨论】:

  • 默认情况下,perl 命令行逐行读取输入(文件或管道)。在这种情况下,您显然不能使用多行模式。

标签: regex perl multiline


【解决方案1】:

一种方法是从perlrun doc slurp 整个文件

特殊值 00 将导致 Perl 以段落模式 slurp 文件。 任何 0400 或以上的值都会导致 Perl 读取整个文件,但是通过 约定值 0777 是通常用于此目的的值。

我稍微修改了示例输入以进行演示:

$ cat ip.txt 
#DEV
#jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
#ems_value=emsdev.example
xyz #DEV
#abc

在 OP 的正则表达式中添加 -0777 选项

$ perl -0777 -pe 's/#DEV\n#(.*)/#DEV\n\1/g' ip.txt 
#DEV
jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
ems_value=emsdev.example
xyz #DEV
abc

如果#DEV 必须仅在行首匹配,请使用m 标志

$ perl -0777 -pe 's/^#DEV\n#(.*)/#DEV\n\1/mg' ip.txt 
#DEV
jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
ems_value=emsdev.example
xyz #DEV
#abc


也可以使用正向后视:

$ perl -0777 -pe 's/^#DEV\n\K#//mg' ip.txt 
#DEV
jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
ems_value=emsdev.example
xyz #DEV
#abc


另请注意: What is the difference between \1 and $1 in a Perl regex?

【讨论】:

    【解决方案2】:

    只需使用变量作为标志。如果您看到#DEV,请将其设置为 1,否则将其设置为 0。如果设置了标志,请删除前导 # - 但在设置之前检查标志!

    perl -pe 's/^#// if $delete; $delete = /^#DEV$/;' input-file
    

    【讨论】:

    • 再次@choroba 请描述您的答案解决的问题。您的努力仅服务于 OP,并且只有在您的分析正确的情况下。这不是 Stack Overflow 的工作方式。
    • @Borodin:我的回答试图解决问题中提出的问题:如何取消注释环境名称和给定环境名称的以下行。
    • @Borodin:对不起,应该是“如何取消注释给定环境名称后面的行”。
    【解决方案3】:

    你可以试试这样的:

    perl -pe'if ($a==1) {s/^#//;$a=0;} $a=1 if (/^#DEV/)'
    

    【讨论】:

      猜你喜欢
      • 2013-08-22
      • 2016-10-29
      • 1970-01-01
      • 2017-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多