2012-06-05 11 views
6

Nowość w Perlu.Selektywne dzielenie ciągu znaków w języku Perl

muszę przeanalizować raport, który wygląda tak:

[email protected]@[email protected]@[email protected] 

użyłem:

my @fields = split(/@/, $line, 6); 

Większość czasu to działa dobrze, ale czasami komunikat o błędzie będzie zawierać adres e-mail i cały tekst po symbolu @ w tym e-mailu, aż koniec napisu zakończy się na moim identyfikatorze wiadomości.

Pomyślałem o sprawdzeniu ilości znaków @ i analizie warunkowej, ale czy jest lepszy sposób?

EDIT:

Pożądana wyjście jest listą ciągów, z komunikatem o błędzie zawierającego co przyszedł w nim (w tym okolicznościowy adres e-mail).

Ponieważ istnieją inne aplikacje korzystające z tego samego raportu, nie mogę zmienić separatora lub wyjść z wyjścia.

Przykładowe linie raportu:

[email protected]@[email protected]@440 4.4.1 Some error [email protected] 
[email protected]@[email protected]@550 5.1.1 <[email protected]>... User [email protected] 
[email protected]@[email protected]@550 5.1.1 [email protected] no such [email protected] 

Oczekiwane zawartość @fields po parsowania linii 1:

2012-05-29 
joedoe 
example.com 
AB99-5 
440 4.4.1 Some error occurred 
XYZ35 

i po parsowania wiersz 2:

2012-05-29 
foobar 
invalid.com 
ZZ88-6 
550 5.1.1 <[email protected]>... User Unknow 
GGH93 
+1

Czy możesz wyjaśnić, co żądane wyjście? Lista ciągów? – kevlar1818

+2

to trochę trudny projekt, ponieważ twój separator ** może ** być częścią danych. Jeśli masz dostęp do generatora raportów, zastanawiałabym się, czy nie usunąć komunikatu o błędzie lub zmienić znak separatora ... – kratenko

+0

Czy możesz podać przykład specjalnego komunikatu o błędzie z adresem e-mail? – simbabque

Odpowiedz

1

podobne do odpowiedzi daxim, ale inny sposób pisania go:

my $re = '^' . '([^@]*)@'x4 . '(.*)@([^@]*)$'; 
my @fields = $line =~ /$re/; 

Można też zrobić sprawdzając jakiś błąd tutaj:

my @fields = $line =~ /$re/ or die "can't parse '$line'"; 
+0

Heads up: Miałem błąd, moim zamiarem było, aby dwie części wiadomości e-mail były przetwarzane jako jeden token, stąd wyniki naszych programów są teraz inne. – daxim

+0

@daxim, ale wydaje się, że jest to pożądany wynik, przynajmniej tak, jak pokazano w przykładach pytań. – Qtax

+0

Masz rację, dzisiaj robię zbyt wiele błędów. – daxim

0

Najprostszym sposobem obsłużyć to będzie zmiana @ na inny, znacznie mniej powszechny ogranicznik li ke ;;;;

+1

Z pytania OP: "Ponieważ istnieją inne aplikacje korzystające z tego samego raportu, nie mogę zmienić separatora lub wyjść z wyjścia." – kevlar1818

4

Jeśli $ teststr zawiera na przykład: '2012-05-29 @ emaillocalpart @ emaildomain @ customerid @ error @ me @ ssage @ messageid';

następujący kod:

my @fields2=split('@',$teststr); 
my @[email protected][0 .. 3]; 
my $finalat=$#fields2-1; 
my $errormessage=join('@',@fields2[4 .. $finalat]); 
push(@finalfields,$errormessage); 
push(@finalfields,$fields2[$#fields2]); 

print Data::Dumper->Dump([@finalfields])."\n"; 

daje następujący wynik:

$VAR1 = '2012-05-29'; 
$VAR2 = 'emaillocalpart'; 
$VAR3 = 'emaildomain'; 
$VAR4 = 'customerid'; 
$VAR5 = '[email protected]@ssage'; 
$VAR6 = 'messageid'; 

Przepraszamy - to raczej gadatliwy rozwiązanie. Można również zrobić to samo w jednym wyrażeniu regularnym:

$teststr=~/(.[^@]*)@(.[^@]*)@(.[^@]*)@(.[^@]*)@(.*)@(.[^@]*)/; 
print "$1\n$2\n$3\n$4\n$5\n$6\n"; 
+0

Po prostu testowane, działa ładnie, chociaż mój prawdziwy raport ma 16 pól zamiast 6, więc jeden linijka będzie wyglądał nieco brzydiej. :) –

+0

@CleberGoncalves moja odpowiedź będzie działać dla dowolnej liczby pól, bez uciążliwego wyrażenia regularnego. Just fyi :-) – kevlar1818

1

To właściwie analizuje alternatywne adresy e-mail:

$str = '[email protected]@[email protected]@550 5.1.1 <[email protected]>... User [email protected]'; 
#$str= '[email protected]@[email protected]@440 4.4.1 Some error [email protected]'; 

$str =~ s/(\<[^\>]+\>)/!!/; # replace an email address with !! 
$email = $1; # store the email 

@fields = split(/@/,$str); # split on @ 

s/!!/$email/ foreach (@fields); # find the old !! and replace with the email address 

print STDERR map { "$_ \n" } @fields; # print fields to standard error 

Zobacz pracuje here. Zakładamy, że masz tylko jeden opcjonalny e-mail. Przy odrobinie pracy można go zmodyfikować tak, by działał na łańcuch z dowolną liczbą ograniczonych e-maili o wartości < >.

+0

Edytowałem moje pytanie, kiedy wypróbowałem twoje rozwiązanie znalazłem, że raport może zawierać również adres e-mail, który nie jest ograniczony przez <>. Komunikat o błędzie to prawie dowolny tekst. Zostanie dodany do wyrażenia regularnego. –

+0

+1 dla testowych próbek kodu na kodach pocztowych. –

Powiązane problemy