以特定模式插入一条线

时间:2015-10-22 09:54:07

标签: regex perl

我想在几个文件中出现的特定模式中插入一行,我首先尝试用sed做,然后我意识到这个任务的完美工具将是perl。

所以,我试过了(灵感来自这里Multiline search replace with Perl):

perl -i.bak -pe 'BEGIN{undef $/;} s/(.*)markers:(.*)text:(.*)\n/$1markers:$2text:$3\nlink:/smg' myfile

在此档案中:

module_map:
  markers:
    - x: 1
    'y': 1
    text: "hello world"
    popup: true
    - x: 2
    'y': 2
    text: 'hello world'
    popup: false

得到那个:

module_map:
  markers:
    - x: 1
    'y': 1
    text: "hello world"
    link:
    popup: true
    - x: 2
    'y': 2
    text: 'hello world'
    link:
    popup: false

(注意“text:”行后面的“link:”行)

我找不到任何有效的解决方案。你有什么想法吗?
感谢您阅读:)

2 个答案:

答案 0 :(得分:3)

您似乎正在尝试编辑YAML文件。为什么不使用专用模块?

#!/usr/bin/perl
use warnings;
use strict;

use YAML;

my $s = << '---';
module_map:
  markers:
    - x: 1
      'y': 1
      text: "hello world"
      popup: true
    - x: 2
      'y': 2
      text: 'hello world'
      popup: false
---

my $href = Load($s);

for my $inner (@{ $href->{module_map}{markers} }) {
    $inner->{link} = undef if exists $inner->{text};
}

print Dump($href);

请注意,我必须修复输入数据的缩进。在输出中,您将看到

link: ~

我不确定您是否可以link:没有价值(YAMLYAML::Tiny的空值往返~。)

答案 1 :(得分:2)

我不会尝试在regex中完成所有操作。

如果您这样做,这很容易:

 while ( <> ) { 
     print "   link:\n" if m/popup/;
     print;
 }

你可以单行:

perl -pe 'print "   link:\n" if m/popup/;'

如果您查看perlrun或通过-MO=Deparse执行此操作,-p标记的功能就是包含您的可执行文件&#39;东西:

LINE: while (defined($_ = <ARGV>)) {
    print "   link:\n" if /popup/;
}
continue {
    die "-p destination: $!\n" unless print $_;
}

这意味着你可以做一个简单的s///模式转换。您甚至可以在使用-i进行就地编辑的同时执行此操作。

注意(如评论中所述)可以在perlre中找到有关m//s///的更多信息 - m/表示模式匹配。如果您没有另行说明,则默认为$_的当前内容。

s///是一种sed风格的模式替换。例如。 s/replacethis/withthis/。它默认也适用于$_

如果你的逻辑比这复杂一点(这样可以很好地处理你的样本数据),那么根据记录分隔符来考虑可能是有用的 - 你可以将$/设置为记录分隔符,所以你可以在一个&#34; go&#34;中处理一个块。您可以在perlvar中查看更多相关信息 - 默认情况下,它是&#34;换行&#34;所以你一次迭代一行文件,但你可以将它设置为任何字符串值。 (但请注意 - 不是正则表达式)。或者将其设置为undefined,然后它将一次性读取整个文件。

E.g。在您的上方,您可以将其设置为&#39; - &#39;因此你最终得到:

local $/ = '-'; 

while ( <> ) {
    if ( m/text/ and m/popup/ ) {
        s/^(\s*popup)/    link:\n$1/m;
    }
    print; 
}
正则表达式末尾的

/m(也在perlre中描述)表示跨越多行&#39;。这是必需的,因为我们正在使用多行块。