2010-11-17 68 views
2

昨天我在這裏問了一個關於onelinermjschultz的問題,給了我一個答案,我立即愛上了:) Awk剛剛銷燬了手頭的任務,解析了一個大日誌文件(500+ MB)在幾秒鐘內。現在我試圖將我的其他線索移植到awk上。awk從maillog解析唯一IP地址

這是一個問題:

grep "pop3\[" maillog | grep "User logged in" | 
egrep -o '([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}' | sort -u 

我需要使用POP3所有唯一的IP地址列表連接到郵件服務器。

這是一個示例日誌條目:

Nov 15 00:49:21 hostname pop3[19418]: login: [10.10.10.10] username plaintext 
User logged in 

所以我找到含有「POP3」的所有線條和我分析他們部分「登錄的用戶」。接下來,我使用egrep和一個正則表達式來匹配IP地址,我使用排序來過濾出重複地址。

這是我到目前爲止有我的awk的版本:

awk '/pop3\[.*.User logged in/ {ip[$7]=0} END {for (address in ip) 
{ print address} }' maillog 

這完美的作品,但因爲始終不是所有的日誌條目是相同的,例如有時IP被移動到了8場喜歡這裏:

Nov 15 10:42:40 hostname pop3[2232]: login: hostname.domain.com [20.20.20.20] 
username plaintext User logged in 

用awk捕捉這些條目的最佳方法是什麼?

一如既往感謝事先所有偉大的迴應,你教我這麼多已經:)

回答

3

AWK代碼

只是符合您的IP格式...要小心,沒有其他格式...

/pop3\[.*.User logged in/ { 
     where = match($0,/\[[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/) 
     if (where) 
      ip[substr($0,RSTART+1,RLENGTH-1)]=0 
} 

END {for (address in ip) 
{ print address} } 

運行在ideone

+0

完美的代碼!正是我所需要的,並且感謝ideone,直到現在,從來沒有見過該網站,這正在我的書籤工具欄儘快。 – f10bit 2010-11-17 00:55:57

0

這看起來更像是Perl的領土比awk中對我說:

my %ip_addresses =(); 
while (<>) 
{ 
    next unless m/pop3\[/; 
    next unless m/User logged in/; 
    if (my($ip) = $_ =~ m/(\d{1,3} (?: [.] \d{1,3}){3})/msx) 
    { 
     $ip_addresses{$ip} = 1; 
    } 
} 
foreach my $ip (sort keys %ip_addresses) 
{ 
    print "$ip\n"; 
} 

的排序是不完美 - 是字母而不是數字(因此192.1.168.10將出現在9.25.13.26之前)。當然,這可以是固定的。

0

看到和嘗試這些後方法我有一個新的想法。

belisarius的代碼做我要求的,但因爲它必須做所有的正則表達式匹配它不是最快的,速度是我所追求的。

所以我想出了這個,因爲你可以看到「有問題」的日誌行有一個額外的字段,使他們都長13個字段,而不是正常的12,所以我只刪除額外的領域,這給了我IP地址的正確的列表,然後我用awk再次刪除所有重複的條目:

awk '/pop3\[.*.User logged in/ {{if (NF == 13) $7="";gsub(FS "+",FS)};print $7}' 
/var/log/maillog | awk '!($0 in a){a[$0];print}' 

Ideone link,如果你想在行動中看到