Чтение файла журнала - PullRequest
       3

Чтение файла журнала

1 голос
/ 18 апреля 2011

Я хотел бы прочитать файл журнала и разделить его на 4 скаляра.

Это пример файла журнала:

    [time1] [error1] [who is1] mess is here1
    [time2] [error2] mess is here2

И id хотел бы получить эти скаляры:

 ($time, $err, $who, $mess)=('time1', 'error1', 'who is1', 'mess is here1')
 ($time, $err, $who, $mess)=('time2', 'error2', '', 'mess is here2') 

Как это сделать в perl?

Мой код похож на thet, но он не работает:

while (<MYFILE>) {
        chomp;
            ($time, $err, $who, $mess)=($_ =~/\[([.]*)\] \[([.]*)\] (\[([.]*)\]|[ ])([.]*)/);
            $logi.= "<tr><td>$time</td><td>$err</td><td>$who</td><td>$mess</td></tr>\n";

}

Ответы [ 3 ]

6 голосов
/ 18 апреля 2011

Вот способ сделать это немного более читабельным, используя преимущества скомпилированных регулярных выражений и флаг / x, чтобы игнорировать пробелы.

my $block_re = qr{ \[ (.*?) \] }x;    # [some thing]
my $log_re = qr{^
    $block_re \s+ $block_re \s+ (?: $block_re \s+ )?  # two or three blocks
    (.*)                                              # the log message
$}x;

while($line = <$fh>) {
    my @fields = $line =~ $log_re;
    my $message = pop @fields;
    my($time, $err, $who) = @fields;

    print "time: $time, err: $err, who: $who, message: $message\n";
}

Одним из ключевых моментов в регулярном выражении блока является использование «не жадного» оператора сопоставления .*?. Обычно .* соответствует самой длинной строке, что означает, что m{ \[ .* \] }x будет соответствовать всем «[foo] [bar] [baz]», а не только «[foo]». Говоря, что он не жадный, добавив ?, и он будет соответствовать самому короткому, который просто "[foo]".

Другая модификация, которую я сделал, - обрабатывать последнее поле, а не четвертое, как поле сообщения. Я подозреваю, что в вашем формате может быть столько блоков "[foo]", сколько нужно.

2 голосов
/ 18 апреля 2011
my ($time, $err, $who, $mess)=($_ =~/\[(.*?)\]\s+\[(.*?)\]\s+(?:\[(.*?)\]|)\s*(.*)/);
$logi.= "<tr><td>$time</td><td>$err</td><td>".($who||"")."</td><td>$mess</td></tr>\n";

Идея состоит в том, чтобы сопоставить третью позицию с [block] или ничем .Вот что это делает:

(?:\[(.*?)\]|)

$who остается неопределенным, если эта часть не совпадает.* * * * * $who||"" в распечатке состоит в том, чтобы предотвращать предупреждения об использовании неопределенного значения с конкатенацией в нем.

1 голос
/ 19 апреля 2011

Я должен не согласиться с предложениями других ответов использовать не жадные квантификаторы (т. Е. .*?).Предполагая, что ] не является допустимым символом в ваших полях time / error / who, вы не ищете кратчайшую возможную последовательность из любых символов вообще, за которой следует ].Вы ищете самую длинную последовательность не ] символов, которая правильно записана как [^]]*.Делать это таким образом более эффективно (механизм регулярных выражений может немедленно останавливаться, когда он видит ], вместо того, чтобы потенциально сделать много возвратов, чтобы найти альтернативные совпадения), и более точно передает ваши намерения будущим программистам, читающим код.

#!/usr/bin/env perl

use strict;
use warnings;

while (<DATA>) {
  chomp;
  my ($time, $err, $who, $mess) =
    ($_ =~/\[([^]]*)\] \[([^]]*)\] (?:\[([^]]*)\] )?(.*)/);
  $who ||= '(unspecified)';
  print "$time - $err - $who - $mess\n";
}

__DATA__
[time1] [error1] [who is1] mess is here1
[time2] [error2] mess is here2

Вывод:

time1 - error1 - who is1 - mess is here1
time2 - error2 - (unspecified) - mess is here2

Между прочим, основная проблема в вашем начальном регулярном выражении не была жадным совпадением, так или иначе ... Вы пытались сопоставить [.]*, который будет соответствовать только последовательностямиз буквальных . символов;он бы работал нормально для записи в журнале "[...] [..] [......] ..........", но не будет совпадать для записи, содержащейсимволы, отличные от разделителей [], пробелы, разделяющие поля, и точки для содержимого полей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...