昨天我在这里问了一个关于oneliner的问题,mjschultz给了我一个答案,我立刻爱上了:) Awk刚刚破坏了手头的任务,解析了一个大的日志文件(500+) MB)在几秒钟内。现在我正试图将我的其他oneliners移植到awk。
这是有问题的一个:
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地址,我使用sort来过滤掉重复的地址。
这是我到目前为止我的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捕获这些条目的最佳方法是什么?
一如既往地感谢你提前做出的所有好的回应,你已经教会了我很多:)
答案 0 :(得分: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} }
运行
答案 1 :(得分: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之前)。当然,这可以修复。
答案 2 :(得分: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如果您想查看实际操作中的代码