2015-07-10 274 views
0

所以我有一个看起来是这样的一个日志文件的文本块:正则表达式/ Perl来匹配包含字符串

EVENT-header 
apple 
orange 
peach 
blueberry 

EVENT-header 
bike 
car 
blueberry 

EVENT-header 
reddit 
hacker news 
stack overflow 
slashdot? 
voat 

我所试图做的是提取文本的块(从事件 - 在下一个EVENT-header之前添加到两个换行符的头部)包含单词“桃子”。

我认为这是一个正则表达式可以解决的问题,但是我很难做出这样的正则表达式。这是我到目前为止:

's/EVENT-header((?!\n\n).)+peach((?!\n\n).)+\n\n/&/p' 

我不是这方面的专家。有使用正则表达式/ perl的简单方法吗?

回答

2

为此,您可以轻松地使用段落模式使perl的读取空行

perl -00 -ne'print if /peach/' logfile.log 

分隔文本块,如果你喜欢一个完整的程序文件,然后它看起来像这样

use strict; 
use warnings; 

open my $fh, '<', 'logfile.log' or die $!; 

{ 
    local $/ = ''; 

    while (<$fh>) { 
     print if /peach/; 
    } 
} 
0

有多种方法可以做到这一点,用多正则表达式匹配是一个很好的候选人。如果数据文件与出现的数据文件一样规则,特别是每个由“EVENT-header”标记分隔的“记录”,那么您还可以使用设置$ /(又名$ RS又名$ INPUT_RECORD_SEPARATOR)的技巧作为这个标记然后将文件sl成一个数组。您将为文件中的每个记录获取一个数组条目,然后循环访问该数组,然后选择与“桃子”匹配的元素并打印出包含整个记录的数据。

例如:

#!/usr/bin/perl -w 
use strict; 

$/='EVENT-header'; 
my (@entries, $entry); 
my $infile = 'data.txt'; 

open(IN, "<$infile") or die "Aaargh: $^E\n"; 
@entries = <IN>; 
chomp @entries; 
close(IN); 

foreach $entry (@entries) 
{ 
    if ($entry =~ m/peach/) 
    { 
    print "matching entry: $entry\n"; 
    } 
} 
+1

可能是值得一提的是'chomp'删除记录分隔符,它可以使事情有点清洁器。例如。你可以设置'$ /'为“\ n \ nEVENT-header \ n”,然后'chomp'将它们从块中移出。 – Sobrique

0

鲍罗丁已经为您的问题提供了最佳解决方案。但这里是万一代码你不想用一个班轮:

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

local $/ = ""; #to enable paragraph mode 

open my $fh, "<", "input.log" or die "Unable to open file: $!"; 

while (my $line = <$fh>) 
{ 
    chomp $line; 
    if ($line =~ m/peach/) 
    { 
     print $line, "\n"; 
    } 
} 

输出:

EVENT-header 
apple 
orange 
peach 
blueberry