Используйте «захватные скобки» для определения битов, с которыми вы хотите иметь дело.
if ($line =~ m/(.* $mon $day) \d{2}:\d{2}:\d{2} $year:.*
(ERROR:|backup-date=|backup-size=|
backup-time=|backup-status)/x) {
Вам нужно будет сделать операцию над вторым набором скобок - теми, которые окружают начало различных ключевых слов. Возможно, вам придется нарезать их на кусочки внутри условия.
Когда все данные извлечены в переменные, используйте Text :: CSV для обработки вывода CSV (и ввода).
Существует множество модулей для обработки HTML или XML (более 2000, и я думаю, более 3000, с HTML в их названии - я случайно посмотрел вчера). Многие из них не применимы, но CPAN - ваш друг.
Ответы на вопросы, заданные комментариями
Могу ли я разделить их на отдельные переменные? Первая часть дает мне дату / время, которое мне нужно. Затем следующий фильтр дает мне 1) ошибка: 2) дата резервирования = 3) размер резервной копии = ... и т. Д.
Больше или меньше. К сожалению, вы не показываете некоторые репрезентативные строки ввода, что означает, что трудно сказать, что может быть лучше. Тем не менее, похоже, что такая схема, как:
while (my $line = <$fh>)
{
chomp $line;
if ($line =~ m/(.* $mon $day) \d\d:\d\d:\d\d $year:/)
{
my $date = $1;
my %items = ();
$line =~ s/.* $mon $day \d\d:\d\d:\d\d $year://;
while ($line =~ m/(ERROR|backup-date|backup-size|
backup-time|backup-status)
[:=]([^:]+)/x)
{
my $key = $1;
my $val = $2;
$items{$key} = $val;
$line =~ s/$key[:=]$val[:=]?//;
}
# The %items hash contains the split out information.
# Now write the data for this line of the log file.
}
}
Возможно, есть более эффективные способы обработки обрезки (но это Perl, так что TMTOWTDI), но основная идея здесь состоит в том, чтобы поймать интересные строки, а затем постепенно вырезать интересующие фрагменты из строки, поэтому строка уменьшается на каждой итерации (следовательно, в конечном итоге завершается внутренний цикл while).
Обратите внимание на использование модификатора /x
, чтобы обеспечить более удобочитаемое разделение на регулярные выражения (я тоже отредактировал исходную версию ответа). Я также допустил, чтобы за «ОШИБКОЙ» следовал «=
», а за другими ключевыми словами следовало бы «:
»; кажется маловероятным, что вы получите ложные совпадения таким образом, и это упрощает операции замены регулярных выражений. Первоначальное сопоставление с образцом больше не требует наличия одного из подразделов. Вы должны самостоятельно оценить, имеют ли значение эти небольшие изменения (которые могут привести к несоответствующей информации) или нет. Для большинства моих целей вероятность несоответствия достаточно мала, чтобы не быть проблемой, но по юридическим причинам она может быть неприемлемой для вас.
Отвечая на вопросы, заданные 'answer'
Я произвел некоторые данные:
Wed Jul 30 00:49:51 2010: test203.bak_lvm:backup:INFO: backup-size=417.32 GB
Wed Jul 30 00:49:52 2010: test203.bak_lvm:backup:INFO: backup-time=04:49:51
Wed Jul 30 00:49:53 2010: test203.bak_lvm:backup:INFO: backup-status=Backup succeeded
Wed Jul 30 00:49:51 2010: backup-size=417.32 GB:backup-time=04:49:51:backup-status=Backup succeeded
Я взял сценарий в ответ, взломал и проинструктировал его - сделав его автономным.
Я также убрал зависимость от конкретных файлов - он читает стандартный ввод и записывает в стандартный вывод. Это облегчает мое тестирование и делает код более гибким.
use strict;
use warnings;
use constant debug => 0;
my $mon = 'Jul';
my $day = 30;
my $year = 2010;
while (my $line = <>)
{
chomp $line;
print "Line: $line\n" if debug;
if ($line =~ m/(.* $mon $day) \d\d:\d\d:\d\d $year:/) #Mon Jul 26 22:00:02 2010:
{
print "### Scan\n";
my $date = $1;
print "$date\n";
my %items = ();
$line =~ s/.* $mon $day \d\d:\d\d:\d\d $year://;
print "Line: $line\n" if debug;
while ($line =~ m/(ERROR|backup-date|backup-size|backup-time|backup-status)[:=]([^:]+)/)
{
my $key = $1;
my $val = $2;
$items{$key} = $val;
$line =~ s/$key[:=]$val[:=]?//;
print "$key=$val\n";
print "Line: $line\n" if debug;
}
print "### Verify\n";
for my $key (sort keys %items)
{
print "$key = $items{$key}\n";
}
}
}
Вывод, который я получаю:
### Scan
Wed Jul 30
backup-size=417.32 GB
### Verify
backup-size = 417.32 GB
### Scan
Wed Jul 30
backup-time=04
### Verify
backup-time = 04
### Scan
Wed Jul 30
backup-status=Backup succeeded
### Verify
backup-status = Backup succeeded
### Scan
Wed Jul 30
backup-size=417.32 GB
backup-time=04
backup-status=Backup succeeded
### Verify
backup-size = 417.32 GB
backup-status = Backup succeeded
backup-time = 04
Цикл проверки выводит данные из хэша '%items
' довольно счастливо. Когда значение отладки установлено в 1 вместо 0, я получаю вывод:
Line: Wed Jul 30 00:49:51 2010: test203.bak_lvm:backup:INFO: backup-size=417.32 GB
### Scan
Wed Jul 30
Line: test203.bak_lvm:backup:INFO: backup-size=417.32 GB
backup-size=417.32 GB
Line: test203.bak_lvm:backup:INFO:
### Verify
backup-size = 417.32 GB
Line: Wed Jul 30 00:49:52 2010: test203.bak_lvm:backup:INFO: backup-time=04:49:51
### Scan
Wed Jul 30
Line: test203.bak_lvm:backup:INFO: backup-time=04:49:51
backup-time=04
Line: test203.bak_lvm:backup:INFO: 49:51
### Verify
backup-time = 04
Line: Wed Jul 30 00:49:53 2010: test203.bak_lvm:backup:INFO: backup-status=Backup succeeded
### Scan
Wed Jul 30
Line: test203.bak_lvm:backup:INFO: backup-status=Backup succeeded
backup-status=Backup succeeded
Line: test203.bak_lvm:backup:INFO:
### Verify
backup-status = Backup succeeded
Line: Wed Jul 30 00:49:51 2010: backup-size=417.32 GB:backup-time=04:49:51:backup-status=Backup succeeded
### Scan
Wed Jul 30
Line: backup-size=417.32 GB:backup-time=04:49:51:backup-status=Backup succeeded
backup-size=417.32 GB
Line: backup-time=04:49:51:backup-status=Backup succeeded
backup-time=04
Line: 49:51:backup-status=Backup succeeded
backup-status=Backup succeeded
Line: 49:51:
### Verify
backup-size = 417.32 GB
backup-status = Backup succeeded
backup-time = 04
Операции замены удаляют ранее согласованную часть строки. Существуют способы продолжения матча, на котором вы остановились - см. \G
на странице 'perlre' .
Обратите внимание, что регулярное выражение создано для остановки на первом двоеточии после слова "двоеточие или равно" после ключевого слова. Это означает, что оно сокращает время резервного копирования. Один мораль - «не используйте разделитель, который может появляться в данных». Другой - «предоставьте образцы данных, чтобы люди могли вам легче помочь». Другой - «предоставляйте полные, но минимальные рабочие скрипты, где это возможно».
Обработка данных образца
Теперь, когда у нас есть пример входных данных, мы можем видеть, что вам нужна немного другая обработка. Этот скрипт:
use strict;
use warnings;
use constant debug => 0;
my $mon = 'Jul';
my $day = 28;
my $year = 2010;
my %items = ();
while (my $line = <>)
{
chomp $line;
print "Line: $line\n" if debug;
if ($line =~ m/(.* $mon $day) \d\d:\d\d:\d\d $year: ([^:]+):backup:/) #Mon Jul 26 22:00:02 2010:
{
print "### Scan\n" if debug;
my $date = $1;
my $set = $2;
print "$date ($set): " if debug;
$items{$set}->{'a-logdate'} = $date;
$items{$set}->{'a-dataset'} = $set;
if ($line =~ m/(ERROR|backup-date|backup-size|backup-time|backup-status)[:=](.+)/)
{
my $key = $1;
my $val = $2;
$items{$set}->{$key} = $val;
print "$key=$val\n" if debug;
}
}
}
print "### Verify\n";
for my $set (sort keys %items)
{
print "Set: $set\n";
my %info = %{$items{$set}};
for my $key (sort keys %info)
{
printf "%s=%s;", $key, $info{$key};
}
print "\n";
}
дает этот результат в файле данных примера.
### Verify
Set: db9.abc.bak
a-dataset=db9.abc.bak;a-logdate=Wed Jul 28;backup-date=20100728000004;
Set: test203.bak_lvm
a-dataset=test203.bak_lvm;a-logdate=Wed Jul 28;backup-size=417.32 GB;backup-status=Backup succeeded;backup-time=04:49:51;
Обратите внимание, что теперь у нас есть примеры данных, и мы видим, что в строке имеется только одна пара ключ / значение, но в день выполняется резервное копирование нескольких систем.Таким образом, внутренний цикл while становится простым if.Распечатка происходит в конце.И я использую «двухуровневый» хэш.%items
содержит запись для каждого набора данных;запись, однако, является ссылкой на хеш.Новичкам необязательно что-то играть, но с предыдущим кодом это стало совершенно естественным.Также обратите внимание, что эта версия не взламывает строки - в этом нет необходимости, поскольку в каждой строке содержится только одна партия данных.
Можно ли ее улучшить, да, несомненноЭто работает?Да, более или менее ... Можно ли это взломать в форму?Да, его можно взломать, чтобы он работал как вам нужно.