Чтение между определенными строками - PullRequest
0 голосов
/ 20 декабря 2010

У меня есть большой файл, который мне нужен, чтобы извлечь только определенные фрагменты информации.Я нашел много примеров в Интернете, но я не могу заставить их работать для моего конкретного экземпляра.У меня есть файл 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

Ответы [ 5 ]

3 голосов
/ 20 декабря 2010

Попробуйте прочитать в режиме абзаца:

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
0 голосов
/ 21 декабря 2010

Вот способ сделать это:

#!/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
0 голосов
/ 21 декабря 2010

Если честно, «лучшее» решение зависит от вашего файла. Например:

  • , если файл огромен, то все это может быть нецелесообразно с помощью <> или $ _, тогда как если он "маленький", это будет хорошо.
  • имеет ли файл такую ​​же регулярную структуру, как в приведенном примере? В этом фрагменте блоки встречаются по повторяющемуся графику: блоки 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);
0 голосов
/ 20 декабря 2010

Я думаю, что это достигает того, что вы хотите

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

Это соответствует следующим двум датам: Dec 8 20:00:00 и Dec 8 21:00:00

0 голосов
/ 20 декабря 2010

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;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...