在某些行之间阅读

时间:2010-12-20 18:08:32

标签: perl

我有一个大文件,我只需要提取某些信息。我在网上找到了很多例子,但我无法为我的特定实例工作。我有文件data.log(下面),需要提取所有Stats1计数器,包括上面的数据。这些统计数据有多个实例。我似乎无法得到一个正则表达式来匹配日期AND St​​ats1,然后读取所有内容直到三/ 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

5 个答案:

答案 0 :(得分:3)

尝试阅读段落模式:

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

答案 1 :(得分:0)

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;

答案 2 :(得分:0)

我认为这可以实现你想要的目标

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

它符合以下两个日期:Dec 8 20:00:00Dec 8 21:00:00

答案 3 :(得分:0)

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

  • 如果文件太大,请将其全部放入via&lt;&gt;或$ _可能不明智,而如果它是“小”,那就没问题了。
  • 文件是否具有与所示示例一样的常规结构?在该片段中,块以重复的时间表发生:Stats1块在第3,19,35,......,3 + 16n行并且以“7 + 16n”结束。所以它可能就像读取文件一样简单,如果行号介于3到7之间,则只打印行。

在乐观假设文件结构良好的情况下,它可能就像这样简单:

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

答案 4 :(得分:0)

这是一种方法:

#!/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