在某些行之间读取

问题描述:

我有一个大文件,我只需要提取某些信息。我在网上找到了很多例子,但我无法为我的特定实例工作。我有文件data.log(如下),并且需要将所有Stats1计数器(包括上面的数据)取出。这些统计信息有多个实例。我似乎无法得到一个正则表达式来匹配日期和Stats1,然后读取所有内容,直到三/ n/n/n的....任何帮助非常感谢!在某些行之间读取

# DATA FILE 

Dec 8 20:00:00 
Stats1 
    counter1:  123 
    counter2:  456 
    counter3:  789 



Dec 8 21:00:00 
Stats2 
    counter4:  123 
    counter5:  456 
    counter6:  789 



Dec 8 21:00:00 
Stats1 
    counter1:  123 
    counter2:  456 
    counter3:  789 



Dec 8 21:00:00 
Stats2 
    counter4:  123 
    counter5:  456 
    counter6:  789 
+3

到目前为止你有什么?问题的哪一部分给你带来麻烦? – Quentin 2010-12-20 18:09:49

Edit4:这些意见,这里是希望最终版本:

use strict; 
use warnings; 
use 5.010; 
use Data::Dumper; 

my %counter_vals; 

{ 
    local $/ = "\n\n\n"; 

    while (<DATA>) { 
     my ($date) = /(
        \p{L}{3} 
        \s+ 
        (?:3[0-1]|[1-2][0-9]|[1-9])) 
         .*? 
        Stats1/msxg or next; 
     my @counter_vals = /counter[0-9]+:\s+([0-9]+)/g; 
     push @{$counter_vals{$date}}, @counter_vals; 
    } 
} 
say Dumper \%counter_vals; 
+0

请将您的所有编辑调整为一个解决方案,删除非工作代码片段。 – marcog 2010-12-20 20:53:41

+0

他们工作得很好,只是他们没有做OP的想法:p 但是k。 – Hugmeir 2010-12-20 20:58:49

我想,这达到你想要

/(.+)\nStats1(?:\n.+){3})/g 

什么它下面的两个日期相匹配:Dec 8 20:00:00Dec 8 21:00:00

+0

...假设您已将整个文档放入'$ _' – mob 2010-12-20 19:30:50

+0

对不起,我应该已经更清楚了。在我的脑海里,我确切地知道我的意思,但现在我读了它... – Lozwell 2010-12-20 20:06:52

+0

对不起,我应该更清楚。在我看来,我确切地说明了我的意思,但现在我读了它......我只想拉动Date(上面的Stats1),Stats1 Heading和所有Stats1计数器,而不是任何Stats2信息。 \ n \ n \ n是每次输入后的三个新行。 – Lozwell 2010-12-20 20:15:33

尝试阅读段落模式:

local $/ = ""; 
while (<>) { 
    print "paragraph: $_"; 
} 

我离开搞清楚哪些段落和你想要处理什么。

输出为您的样品数据:

paragraph: # DATA FILE 

paragraph: Dec 8 20:00:00 
Stats1 
    counter1:  123 
    counter2:  456 
    counter3:  789 

paragraph: Dec 8 21:00:00 
Stats2 
    counter4:  123 
    counter5:  456 
    counter6:  789 

paragraph: Dec 8 21:00:00 
Stats1 
    counter1:  123 
    counter2:  456 
    counter3:  789 

paragraph: Dec 8 21:00:00 
Stats2 
    counter4:  123 
    counter5:  456 
    counter6:  789 

说实话,“最好”的解决方案取决于您的文件。例如:

  • 如果该文件是巨大的,通过<在啜这一切>或$ _也许并不明智,而如果它的“小”,这将是罚款。
  • 该文件是否具有与所示样本一样的常规结构?在该片段中,块按重复计划进行:Stats1块位于第3,19,35,...,3 + 16n行,并以“7 + 16n”结尾。所以它可能是因为读文件中,只打印行,如果行号为3和

在乐观假设该文件是结构良好间7模16 ,它可能是那样简单这样简单:

open(IN, "inp.txt") or die; 
while (my $line = <IN>) 
{ 
    chomp $line; 
    if (($. % 16 >= 3) && 
     ($. % 16 <= 7) ) 
    { 
    print "$line\n"; 
    } 
} 
close(IN); 

这里是一个办法做到这一点:

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

local $/ = "\n\n\n"; 
while (<DATA>) { 
    print if/Stats1/; 
} 

__DATA__ 
Dec 8 20:00:00 
Stats1 
    counter1:  123 
    counter2:  456 
    counter3:  789 



Dec 8 21:00:00 
Stats2 
    counter4:  123 
    counter5:  456 
    counter6:  789 



Dec 8 21:00:00 
Stats1 
    counter1:  123 
    counter2:  456 
    counter3:  789 



Dec 8 21:00:00 
Stats2 
    counter4:  123 
    counter5:  456 
    counter6:  789 

输出:

Dec 8 20:00:00 
Stats1 
    counter1:  123 
    counter2:  456 
    counter3:  789 



Dec 8 21:00:00 
Stats1 
    counter1:  123 
    counter2:  456 
    counter3:  789