一次性完成:
use warnings
use strict
*ARGV = *DATA
my %msg
while (<>) {
if (s!^.*postfix/\w+\[.+?\]: (\w+):\s*!!) {
my $key = $1
push @{ $msg{$key}{$1} } => $2
while /\b(to|from|client)=(.+?)(?:,|$)/g
}
}
use Data::Dumper
$Data::Dumper::Indent = 1
print Dumper \%msg
__DATA__
Apr 8 14:22:02 MailSecure03 postfix/smtpd[32388]: BA1CE38965: client=mail.example.com[x.x.x.x]
Apr 8 14:22:03 MailSecure03 postfix/cleanup[32070]: BA1CE38965: message-id=<49dc4d9a.6020...@example.com>
Apr 8 14:22:03 MailSecure03 postfix/qmgr[19685]: BA1CE38965: from=<mailt...@example.com>, size=1087, nrcpt=2 (queue active)
Apr 8 14:22:04 MailSecure03 postfix/smtp[32608]: BA1CE38965: to=<us...@test.com>, relay=127.0.0.1[127.0.0.1]:10025, delay=1.7, delays=1/0/0/0.68, dsn=2.0.0, status=sent (250 OK, sent 49DC509B_360_15637_162D8438973)
Apr 8 14:22:04 MailSecure03 postfix/smtp[32608]: BA1CE38965: to=<us...@test.com>, relay=127.0.0.1[127.0.0.1]:10025, delay=1.7, delays=1/0/0/0.68, dsn=2.0.0, status=sent (250 OK, sent 49DC509B_360_15637_162D8438973)
Apr 8 14:22:04 MailSecure03 postfix/qmgr[19685]: BA1CE38965: removed
Apr 8 14:22:04 MailSecure03 postfix/smtpd[32589]: 62D8438973: client=localhost.localdomain[127.0.0.1]
Apr 8 14:22:04 MailSecure03 postfix/cleanup[32080]: 62D8438973: message-id=<49dc4d9a.6020...@example.com>
Apr 8 14:22:04 MailSecure03 postfix/qmgr[19685]: 62D8438973: from=<mailt...@example.com>, size=1636, nrcpt=2 (queue active)
Apr 8 14:22:04 MailSecure03 postfix/smtp[32417]: 62D8438973: to=<us...@test.com>, relay=y.y.y.y[y.y.y.y]:25, delay=0.19, delays=0.04/0/0.04/0.1, dsn=2.6.0, status=sent (250 2.6.0 <49dc4d9a.6020...@example.com> Queued mail for delivery)
Apr 8 14:22:04 MailSecure03 postfix/smtp[32417]: 62D8438973: to=<us...@test.com>, relay=y.y.y.y[y.y.y.y]:25, delay=0.19, delays=0.04/0/0.04/0.1, dsn=2.6.0, status=sent (250 2.6.0 <49dc4d9a.6020...@example.com> Queued mail for delivery)
Apr 8 14:22:04 MailSecure03 postfix/qmgr[19685]: 62D8438973: removed
该代码首先寻找队列ID(例如上面的
BA1CE38965
和
62D8438973
),我们将其存储在
$key
中。
接下来,我们查找当前行上所有匹配项(由于使用了
/g
开关),这些匹配项看起来像是
to=<...>
,
client=mail.example.com
等,有时会有分隔逗号,有时没有。
模式中值得注意的是:
\b
- 仅匹配单词边界(防止匹配xxxto=<...>
)
(to|from|client)
- 匹配to
、from
或client
(.+?)
- 使用非贪婪量化符匹配字段值
(?:,|$)
- 匹配逗号或字符串末尾,但不捕获到$3
中
非贪婪量化符
(.+?)
强制匹配停止于遇到的第一个逗号,而不是最后一个。否则,在一行中:
to=<foo@example.com>, other=123
你会得到
<foo@example.com>, other=123
作为收件人!
然后,对于每个匹配的字段,我们将其
push
到一个数组的末尾(因为可能有多个收件人),这个数组与队列ID和字段名都有关联。看一下结果:
$VAR1 = {
'62D8438973' => {
'client' => [
'localhost.localdomain[127.0.0.1]'
],
'to' => [
'<us...@test.com>',
'<us...@test.com>'
],
'from' => [
'<mailt...@example.com>'
]
},
'BA1CE38965' => {
'client' => [
'mail.example.com[x.x.x.x]'
],
'to' => [
'<us...@test.com>',
'<us...@test.com>'
],
'from' => [
'<mailt...@example.com>'
]
}
};
现在假设你想打印出队列ID为
BA1CE38965
的消息的所有收件人:
my $queueid = "BA1CE38965";
foreach my $recip (@{ $msg{$queueid}{to} }) {
print $recip, "\n":
}
也许您只想知道有多少收件人:
print scalar @{ $msg{$queueid}{to} }, "\n";
如果您愿意假定每个消息只有一个客户端,请使用以下方式访问该消息:
print $msg{$queueid}{client}[0], "\n";