여러 개의 GB 메일 서버 로그 파일과 ~ 350k 개의 메시지 ID 목록이 있습니다. 나는 긴 목록에서 ID가 큰 로그 파일 행에서 빼 할 ... 내가 지금보다 더 빨리 원하는 ... 현재 나는 펄에서 할 :메일 서버 로그 필터링
#!/usr/bin/perl
use warnings;
#opening file with the list - over 350k unique ID
open ID, maillog_id;
@lista_id = <ID>;
close ID;
chomp @lista_id;
open LOG, maillog;
# while - foreach would cause out of memory
while (<LOG>) {
$wiersz = $_;
my @wiersz_split = split (' ' , $wiersz);
#
foreach (@lista_id) {
$id = $_;
# ID in maillog is 6th column
if ($wiersz_split[5] eq $id) {
# print whole row when matched - can be STDOUT or file or anything
print "@wiersz_split\n";
}
}
}
close LOG;
그것은 작동 하지만 속도가 느립니다 ... 로그의 모든 행은 ID 목록과 비교됩니다. 데이터베이스를 사용하고 일종의 조인을 수행해야합니까? 또는 부분 문자열을 비교합니까?
로그 분석을위한 도구가 많이 있습니다 (예 : pflogsumm ... 그러나 그것은 단지 요약합니다. 예 : 단지 변수를 증가 - 동일 pflogsumm 등입니다 ... 나는
grep -c "status=sent" maillog
그것은 빠르지 만 쓸모가있을 것입니다 사용할 수 있습니다 그리고 내 로그 파일을 필터링 후 사용한다.
제안 사항?
-------------------
감사합니다. Dallaylaen, 나는 (@lista_id
대신 내부 foreach 문)이 함께 succeded :
%lista_id_hash
키를 내 ID 목록에서 가져온 항목은 해시 테이블입니다
if (exists $lista_id_hash{$wiersz_split[5]}) { print "$wiersz"; }
. 그것은 초고속으로 작동합니다. 350KB 이상의 ID를 가진 4,6GB 로그 파일을 처리하는 데는 흥미로운 로그를 필터링하는 데 1 분도 걸리지 않습니다.
내 제안은 비슷한 접근 방식을 제공합니다 :'my % known = map {$ _ => 1} @lista_id; ' –
@wk :'map' 또는'for'는 여기에 해당하지만 더 신중한 접근 방법은 '@ lista_id'를 건너 뛰고'while ()'루프 안에'% known '을 채우려면 약간 메모리 사용량을 줄일 수 있습니다. –
Dallaylaen