Perl: удаление нескольких строк восстановления, где встречается определенный критерий
У меня есть данные, которые выглядят как ниже, фактический файл длиной в тысячи строк.
Event_time Cease_time
Object_of_reference
-------------------------- --------------------------
----------------------------------------------------------------------------------
Apr 5 2010 5:54PM NULL
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSJN1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=LUGALAMBO_900
Apr 5 2010 5:55PM Apr 5 2010 6:43PM
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSJN1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=LUGALAMBO_900
Apr 5 2010 5:58PM NULL
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSCC1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=BULAGA
Apr 5 2010 5:58PM Apr 5 2010 6:01PM
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSCC1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=BULAGA
Apr 5 2010 6:01PM NULL
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSCC1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=BULAGA
Apr 5 2010 6:03PM NULL
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSJN1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=KAPKWAI_900
Apr 5 2010 6:03PM Apr 5 2010 6:04PM
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSJN1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=KAPKWAI_900
Apr 5 2010 6:04PM NULL
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSJN1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=KAPKWAI_900
Apr 5 2010 6:03PM Apr 5 2010 6:03PM
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSCC1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=BULAGA
Apr 5 2010 6:03PM NULL
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSCC1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=BULAGA
Apr 5 2010 6:03PM Apr 5 2010 7:01PM
SubNetwork=ONRM_RootMo,SubNetwork=AXE,ManagedElement=BSCC1,BssFunction=
BSS_ManagedFunction,BtsSiteMgr=BULAGA
Как видите, у каждого файла есть заголовок, который описывает, что обозначают различные поля (время начала события, время прекращения события, затронутый элемент). Заголовок сопровождается рядом тире.
Моя проблема в том, что в данных вы видите ряд записей, где время прекращения равно NULL, т.е. событие все еще активно. Все такие записи должны идти, т. Е. Для каждого элемента, для которого время прекращения тревоги равно NULL, время начала, время прекращения (в данном случае NULL) и фактический элемент должны быть удалены из файла.
В остальных данных также должен идти весь текст, начиная со слова SubNetwork до BtsSiteMgr=. Вместе с заголовками и тире.
Окончательный вывод должен выглядеть следующим образом:
Apr 5 2010 5:55PM Apr 5 2010 6:43PM
LUGALAMBO_900
Apr 5 2010 5:58PM Apr 5 2010 6:01PM
BULAGA
Apr 5 2010 6:03PM Apr 5 2010 6:04PM
KAPKWAI_900
Apr 5 2010 6:03PM Apr 5 2010 6:03PM
BULAGA
Apr 5 2010 6:03PM Apr 5 2010 7:01PM
BULAGA
Ниже приведен скрипт на Perl, который я написал. Он позаботился о заголовках, тире, NULL-записях, но мне не удалось удалить строки, следующие за NULL-записями, чтобы получить вышеуказанный вывод.
#!/usr/bin/perl
use strict;
use warnings;
$^I=".bak" #Backup the file before messing it up.
open (DATAIN,"<george_perl.txt")|| die("can't open datafile: $!"); # Read in the data
open (DATAOUT,">gen_results.txt")|| die("can't open datafile: $!"); #Prepare for the writing
while (<DATAIN>) {
s/Event_time//g;
s/Cease_time//g;
s/Object_of_reference//g;
s/\-//g; #Preceding 4 statements are for cleaning out the headers
my $theline=$_;
if ($theline =~ /NULL/){
next;
next if $theline =~ /SubN/;
}
else{
print DATAOUT $theline;
}
}
close DATAIN;
close DATAOUT;
Пожалуйста, помогите указать любые изменения, которые мне нужно внести в сценарий, чтобы он выдал необходимый вывод.
3 ответа
Ваши данные поступают в виде набора из 3 строк, поэтому один из подходов заключается в том, чтобы организовать синтаксический анализ следующим образом:
use strict;
use warnings;
# Ignore header junk.
while (<>){
last unless /\S/;
}
until (eof) {
# Read in a set of 3 lines.
my @lines;
push @lines, scalar <> for 1 .. 3;
# Filter and clean.
next if $lines[0] =~ /\sNULL\s/;
$lines[2] =~ s/.+BtsSiteMgr=//;
print @lines[0,2];
}
Выглядит как хороший кандидат на небольшой разделитель входных записей ($/
Обман. Идея состоит в том, чтобы манипулировать им так, чтобы он работал с одной записью за раз, а не с одной строкой по умолчанию.
use strict;
use warnings;
$^I = '.bak';
open my $dataIn, '<', 'george_perl.txt' or die "Can't open data file: $!";
open my $dataOut, '>', 'gen_results.txt' or die "Can't open output file: $!";
{
local $/ = "\n\t"; # Records have leading tabs
while ( my $record = <$dataIn> ) {
# Skip header & records that contain 'NULL'
next if $record =~ /NULL|Event_time/;
# Strip out the unwanted yik-yak
$record =~ s/SubNetwork.*BtsSiteMgr=//s;
# Print record to output file
print $dataOut $record;
}
}
close $dataIn;
close $dataOut;
Обратите внимание на следующее:
- использование более безопасной формы с тремя аргументами
open
(форма с двумя аргументами - это то, что вы показали) - использование скалярных переменных, а не голых слов для определения файловых дескрипторов
- использование
local
Ключевое слово и дополнительные локоны, чтобы изменить определение$/
только когда нужно. - второй
s
вs/SubNetwork.*BtsSitMgr=//s
позволяет совпадения по нескольким строкам.
s/^.*NULL\r?\n.*\r?\n.*\r?\n//mg;
следует отфильтровать строки, которые заканчиваются NULL
плюс две следующие строки.