更正多线搜索的语法并在perl中替换,因此不会打印不匹配的行

时间:2016-05-13 07:35:31

标签: regex perl

我尝试进行多行搜索和替换,但不能完全正确,只输出我需要的内容。

我想从直线跟随虚线的每一行中提取时间,以便输入:

--------------------
2016-05-13 10:00:00 abc
2016-05-13 10:00:01 def
2016-05-13 10:00:02 ghi
--------------------
2016-05-13 10:00:03 jkl
2016-05-13 10:00:04 mno

应该产生这样的输出:

10:00:00
10:00:03

这个命令看起来似乎在每次比赛中都被正确替换,但它也打印了线的其余部分以及不匹配的每一行。

perl -0ne 'print if s/-{20}\n\d{4}-\d\d-\d\d (\d\d:\d\d:\d\d)/$1/g'

在正则表达式的末尾添加.*并没有多大帮助,因为它只会在匹配后删除其余的行,并且添加/s会使命令输出仅在第一次被替换时匹配。

如何只获得所需的输出?

修改

Sobrique的回答利用虚线(或其中的一部分)作为记录分隔符,但我也感兴趣的是,如果虚线<<>>之后我将如何获得所需的数据所需的输出。

我想从上面的输入中得到10:00:02,即相当于匹配正则表达式^\d{4}-\d\d-\d\d (\d\d:\d\d:\d\d).*\n-{20}中的反向引用(我相信插入符号不太重要,我相信)。我可以在执行Sobrique的解决方案之前和之后使用tac,但是希望看到如何在不执行此操作的情况下实现此目的。

1 个答案:

答案 0 :(得分:1)

好的,你需要知道的是:

-0设置记录分隔符。你可能不想这样做。

-n告诉perl以类似于grep / sed / awk的方式迭代STDIN(或指定的文件)。

-e指定要运行的代码。

你的代码中发生的事情,意味着如果该模式匹配测试,perl正在打印整个块&#39; - 这是整个文件。

我建议改为你想要的是:

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

local $/ = '--'; 
while ( <DATA> ) {
   print $1,"\n" if m/ (\d\d:\d\d:\d\d)/;
}

__DATA__
--------------------
2016-05-13 10:00:00 abc
2016-05-13 10:00:01 def
2016-05-13 10:00:02 ghi
--------------------
2016-05-13 10:00:03 jkl
2016-05-13 10:00:04 mno

或作为一个班轮:

perl -ne 'BEGIN { $/ = "--" } print $1,"\n" if m/ (\d\d:\d\d:\d\d)/'

这样做的目的是迭代一个&#39; chunk&#39;一次,基于&#39; - &#39;作为一个记录分隔符,然后抓住一个像时间一样的第一个实例&#39;每个块中的格式。

要回答您的后续问题 - 如果您想在块中抓住最后时间,那么我可能会这样做:

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

local $/ = '--'; 
while ( <DATA> ) {
   my @matches = m/ (\d\d:\d\d:\d\d)/g ;
   print $matches[-1],"\n" if @matches;
}

__DATA__
--------------------
2016-05-13 10:00:00 abc
2016-05-13 10:00:01 def
2016-05-13 10:00:02 ghi
--------------------
2016-05-13 10:00:03 jkl
2016-05-13 10:00:04 mno

将(时间之类)字符串上的所有正则表达式匹配捕获到列表中,然后打印最后一个元素。

匹配包含:

$VAR1 = [
          '10:00:00',
          '10:00:01',
          '10:00:02'
        ];

并且

$VAR1 = [
          '10:00:03',
          '10:00:04'
        ];