我有以下Perl' one-liner'脚本(在线发现,所以不是我的):
perl -lsne '
/$today.* \[([0-9.]+)\]:.+dovecot_(?:login|plain):([^\s]+).* for (.*)/
and $sender{$2}{r}+=scalar (split / /,$3)
and $sender{$2}{i}{$1}=1;
END {
foreach $sender(keys %sender){
printf"Recip=%05d Hosts=%03d Auth=%s\n",
$sender{$sender}{r},
scalar (keys %{$sender{$sender}{i}}),
$sender;
}
}
' -- -today=$(date +%F) /var/log/exim_mainlog | sort
我一直试图了解它的内脏,因为我想修改它以重复使用它的功能。
我得到的一些问题:
我想要实现的目标:
定期获取每个用户在SMTP中继中发送的电子邮件数量(cron job)
如果有不规则数量的电子邮件(例如,1小时时间内有500个),做某事(如关闭服务或发送通知)
为什么我试图实现这一目标: 最近,有人一直在使用我的SMTP服务器发送垃圾邮件,所以我想监视电子邮件活动,以便他们停止滥用SMTP中继资源。 (与安全相关的建议总是受到欢迎,但这个问题不在主题之内。现在尝试着重于脚本)
我不试图实现:
因此,欢迎任何建议,指导和友好评论。我知道这可能是一个主题外的问题,但是我已经在这个问题上挣扎了将近一个星期,而且我对Perl的背景是空的。
提前致谢。
答案 0 :(得分:2)
标志-lsne有什么作用? (据我所知,它至少需要3个不同的旗帜)
-l
导致读入的输入行被自动限制,并且行的行数为
输出打印出来" \ n"自动附加-s
启用切换功能
解析。这就是创建变量$today
的原因,因为a
--today=$(date +%F)
的命令行开关已通过。 -n
围绕着整个&#34; one-liner&#34;在while (<>) { ... }
循环中。
有效地从标准输入读取每一行并运行
那条线上的一个班轮的主体-e
是指示的开关
perl
从命令行执行以下代码
而不是运行包含Perl代码的文件$ sender从哪里获取其值?
我怀疑您$sender
与%sender
混淆。该代码使用$sender{$2}{r}
而未明确提及%sender
。这是Perl的一个功能,称为&#34;自动生成&#34;。基本上,因为我们使用$sender{$2}{r}
,perl会自动创建一个变量%sender
,并添加一个名称为$2
中的任意内容的键,并在%sender
中设置该键的值}是对新哈希的引用。然后,它将新哈希设置为键'r'
和值scalar (split / /,$3)
那个(?:login | plain)细分市场,它们是&#39;变量&#39 ;? (我得到了那个ReGex,我只是不熟悉它)
它说正则表达式的这一部分将匹配'login'
或'plain'
。开头的?:
告诉Perl这些括号仅用于聚类,而不是捕获。换句话说,模式匹配的这部分结果不会存储在$1
,$2
,$3
等变量中。
答案 1 :(得分:1)
-MO=Deparse
是您理解单行的朋友(以及在终端上包含五行的一个内容):
$ perl -MO=Deparse -lsne '/$today.* \[([0-9.]+)\]:.+dovecot_( ...
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE:
while ( defined($_ = <ARGV>) ) {
chomp $_;
$sender{$2}{'i'}{$1} = 1 if
/$today.* \[([0-9.]+)\]:.+dovecot_(?:login|plain):([^\s]+).* for (.*)/
and $sender{$2}{'r'} += scalar split(/ /, $3, 0);
sub END {
foreach $sender (keys %sender) {
printf "Recip=%05d Hosts=%03d Auth=%s\n",
$sender{$sender}{'r'},
scalar keys %{$sender{$sender}{'i'};}, $sender;
}
}
}
-e syntax OK
[为了清晰起见而添加了换行符和缩进]
答案 2 :(得分:1)
标志-lsne有什么作用? (据我所知,它至少需要3个不同的旗帜)
您可以通过运行&#39;〜$ perl -h&#39;来访问可用的perl命令行选项的摘要。在终端。下面将过滤掉您询问的特定命令行选项。
~$ perl -h|perl -ne 'print if /^\s+(-l|-s|-n|-e)/'
-e program one line of program (several -e's allowed, omit programfile)
-l[octal] enable line ending processing, specifies line terminator
-n assume "while (<>) { ... }" loop around program
-s enable rudimentary parsing for switches after programfile
&#39; -s&#39;的两个例子。正在使用的命令行选项。
~$ perl -se 'print "Todays date is $today\n"' -- -today=`date +%F`
Todays date is 2016-10-17
~$ perl -se 'print "The sky is $color.\n"' -- -color='blue'
The sky is blue.
有关这些命令行选项的详细说明,请阅读以下在线文档。 http://perldoc.perl.org/perlrun.html
或者从终端运行以下命令。
~$ perldoc perlrun
与OP的问题无关,我知道这不是一个完整的答案(尽可能多地添加),所以如果这个帖子/答案违反任何SO规则,主持人应该删除它。 THX。