口译与解说修改Perl单线程?

时间:2016-10-16 22:12:30

标签: perl email

我有以下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

我一直试图了解它的内脏,因为我想修改它以重复使用它的功能。

我得到的一些问题:

  • 标志 -lsne 的作用是什么? (据我所知,它至少需要3个不同的旗帜)
  • $ sender 从哪里获取其价值?
  • 那个(?:login | plain)段,它们是'变量&#39 ;? (我得到的是ReGex,我只是不熟悉它)

我想要实现的目标:

  • 定期获取每个用户在SMTP中继中发送的电子邮件数量(cron job)

  • 如果有不规则数量的电子邮件(例如,1小时时间内有500个),做某事(如关闭服务或发送通知)

为什么我试图实现这一目标: 最近,有人一直在使用我的SMTP服务器发送垃圾邮件,所以我想监视电子邮件活动,以便他们停止滥用SMTP中继资源。 (与安全相关的建议总是受到欢迎,但这个问题不在主题之内。现在尝试着重于脚本)

试图实现:

  • 要让第三方完成脚本。 (试着指出我正确的方向,也许是一个例子)

因此,欢迎任何建议,指导和友好评论。我知道这可能是一个主题外的问题,但是我已经在这个问题上挣扎了将近一个星期,而且我对Perl的背景是空的。

提前致谢。

3 个答案:

答案 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。