我尝试进行多行搜索和替换,但不能完全正确,只输出我需要的内容。
我想从直线跟随虚线的每一行中提取时间,以便输入:
--------------------
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
,但是希望看到如何在不执行此操作的情况下实现此目的。
答案 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'
];