在工作中,我们正在开发一个客户可以使用的新闻通讯系统。作为一名实习生,我的工作之一是帮助解决难题中较小的部分。在这种情况下,我需要做的是扫描电子邮件服务器的日志以查找退回邮件,并添加电子邮件以及电子邮件退回到“错误的电子邮件数据库”的原因。
糟糕的电子邮件表格有两列:'email'和'reason' 我使用以下语句从日志中获取信息并将其发送到Perl脚本
grep " 550 " /var/log/exim/main.log | awk '{print $5 "|" $23 " " $24 " " $25 " " $26 " " $27 " " $28 " " $29 " " $30 " " $31 " " $32 " " $33}' | perl /devl/bademails/getbademails.pl
如果你对更高效的awk脚本有兴趣,那么我也很高兴听到这些内容,但我主要关注的是Perl脚本。 awk将“foo@bar.com |反弹的理由”传递给Perl脚本。我想接受这些字符串,将它们拆分为|并将两个不同的部分放入数据库中各自的列中。这就是我所拥有的:
#!usr/bin/perl
use strict;
use warnings;
use DBI;
my $dbpath = "dbi:mysql:database=system;host=localhost:3306";
my $dbh = DBI->connect($dbpath, "root", "******")
or die "Can't open database: $DBI::errstr";
while(<STDIN>) {
my $line = $_;
my @list = # ? this is where i am confused
for (my($i) = 0; $i < 1; $i++)
{
if (defined($list[$i]))
{
my @val = split('|', $list[$i]);
print "Email: $val[0]\n";
print "Reason: $val[1]";
my $sth = $dbh->prepare(qq{INSERT INTO bademails VALUES('$val[0]', '$val[1]')});
$sth->execute();
$sth->finish();
}
}
}
exit 0;
答案 0 :(得分:13)
这样的事情会起作用:
while(<STDIN>) {
my $line = $_;
chomp($line);
my ($email,$reason) = split(/\|/, $line);
print "Email: $email\n";
print "Reason: $reason";
my $sth = $dbh->prepare(qq{INSERT INTO bademails VALUES(?, ?)});
$sth->execute($email, $reason);
$sth->finish();
}
您可能会发现在Perl中完成整个操作会更容易。 “下一步除非/ 550 /”可以取代grep,正则表达式可能会取代awk。
答案 1 :(得分:7)
我不确定你要把什么放在@list中?如果awk为每个条目输入一行,那么你将在$ line中使用它,并且你不需要@list上的for循环。
那就是说,如果你要将它传输到Perl中,为什么首先要使用grep和AWK呢?
#!/ust/bin/perl -w
use strict;
while (<>) {
next unless / 550 /;
my @tokens = split ' ', $_;
my $addr = $tokens[4];
my $reason = join " ", @tokens[5..$#tokens];
# ... DBI code
}
关于DBI调用的附注:您应该使用占位符,以便“错误的电子邮件”无法将SQL注入您的数据库。
答案 2 :(得分:5)
为什么不放弃grep和awk直接去Perl?
免责声明:我没有检查以下代码是否编译:
while (<STDIN>) {
next unless /550/; # skips over the rest of the while loop
my @fields = split;
my $email = $fields[4];
my $reason = join(' ', @fields[22..32]);
...
}
编辑:有关进一步优化,请参阅@dland's comment: - )
希望这有帮助吗?
答案 3 :(得分:5)
答案 4 :(得分:4)
my(@list) = split /\|/, $line;
如果在行尾有额外的管道符号,这将在@list中生成两个以上的条目。为避免这种情况,请使用:
$line =~ m/^([^|]+)\|(.*)$/;
my(@list) = ($1, $2);
正则表达式中的美元可以说是多余的,但也是文档的“行尾”。