解释和修改Perl一行程序?

解释和修改Perl一行程序?,perl,email,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){

我在网上找到了以下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从何处获取其值? 那么呢?:登录|普通段,它们是“变量”吗?我知道那是正则表达式,我只是不熟悉它 我正在努力实现的目标:

获取SMTP中继cron作业中每个用户发送的电子邮件数

如果有不规则数量的电子邮件,比如说1小时内500封,那么可以关闭服务,或者发送通知

为什么我要努力实现这一目标: 最近,有人使用我的SMTP服务器发送垃圾邮件,所以我想监控电子邮件活动,以便他们停止滥用SMTP中继资源。与安全相关的建议总是受欢迎的,但与此问题无关。现在正努力专注于脚本

我不想实现的目标:

让第三方完成脚本。试着给我指出正确的方向,也许是个例子 因此,欢迎任何建议、指导和友好评论。我知道这可能是一个离题的问题,但我已经为此挣扎了将近一周,我的Perl背景是空的

提前感谢。

-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
[为清晰起见添加了换行符和缩进]

-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
[为清晰起见添加了换行符和缩进]

标志-lsne的作用是什么?据我所知,它必须是,至少,3个不同的旗帜在一个

-l使读入的输入行被自动选择,而 打印输出以自动附加\n -s启用交换机 解析。这就是今天创建变量$today的原因,因为 传递了-today=$date+%F的命令行开关。 -n在while{…}循环中包围整个一行。 有效读取标准输入的每一行并运行 那个条线上的一个班轮的主体 -e是指示的开关 perl从命令行执行以下代码,而不是 而不是运行包含Perl代码的文件 $sender从何处获取其值

我怀疑您混淆了$sender和%sender。代码使用$sender{$2}{r},但没有明确提到%sender。这是Perl的一个函数,称为auto vivification。基本上,因为我们使用了$sender{$2}{r},perl自动创建了一个变量%sender,并添加了一个名为$2中任意一个的键,并将%sender中该键的值设置为对新哈希的引用。然后,它将该新散列设置为具有键“r”和标量split/,$3的值

那么呢?:登录|普通段,它们是“变量”吗?我知道那是正则表达式,我只是不熟悉它

这意味着正则表达式的这一部分将匹配“login”或“plain”。开头的?:告诉Perl这些括号仅用于集群,而不是捕获。换句话说,这部分模式匹配的结果将不会存储在$1、$2、$3等变量中。

flag-lsne的作用是什么?据我所知,它必须是,至少,3个不同的旗帜在一个

-l使读入的输入行被自动选择,而 打印输出以自动附加\n -s启用交换机 解析。这就是今天创建变量$today的原因,因为 传递了-today=$date+%F的命令行开关。 -n在while{…}循环中包围整个一行。 有效读取标准输入的每一行并运行 那个条线上的一个班轮的主体 -e是指示的开关 perl从命令行执行以下代码,而不是 而不是运行包含Perl代码的文件 $sender从何处获取其值

我怀疑您混淆了$sender和%sender。代码使用$sender{$2}{r},但没有明确提到%sender。这是Perl的一个函数,称为auto vivification。基本上,因为我们使用了$sender{$2}{r},perl自动创建了一个变量%sender,并添加了一个名为$2中任意一个的键,并将%sender中该键的值设置为对新哈希的引用。然后,它将该新散列设置为具有键“r”和标量split/,$3的值

那么呢?:登录|普通段,它们是“变量”吗?我知道那是正则表达式,我只是不熟悉它

这意味着正则表达式的这一部分将匹配“login”或“plain”。开头的?:告诉Perl这些括号仅用于集群,而不是捕获。换句话说,这部分模式的结果将匹配wil l不能存储在$1、$2、$3等变量中

旗子-lsne的作用是什么?据我所知,它必须是,至少,3个不同的旗帜在一个

通过在终端中运行“~$perl-h”,可以访问可用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
有关这些命令行选项的详细说明,请阅读下面的联机文档。

或者从终端运行下面的命令

~$ perldoc perlrun
与OP中的问题无关,我知道这并不是一个完整的答案,并没有我现在能够添加的那么多,所以如果这个帖子/答案违反了任何so规则,版主应该删除它。Thx

旗子-lsne的作用是什么?据我所知,它必须是,至少,3个不同的旗帜在一个

通过在终端中运行“~$perl-h”,可以访问可用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
有关这些命令行选项的详细说明,请阅读下面的联机文档。

或者从终端运行下面的命令

~$ perldoc perlrun

与OP中的问题无关,我知道这并不是一个完整的答案,并没有我现在能够添加的那么多,所以如果这个帖子/答案违反了任何so规则,版主应该删除它。Thx.

-l、-s、-n和-e记录在每个$sender中。。。将$sender别名添加到foreach迭代的列表的每个元素。但是我想你可能问过%sender,它的元素是由赋值运算符+=和=.正则表达式?:login | plain匹配login和plain。有一种编写多行一行Perl程序的方式。虽然对自己这样做是可以的,就像你可以用一个字母标识符编写没有插入的代码,并且在你的私人时间里不严格使用或刷牙一样,我认为让别人接受这样的东西是非常不礼貌的。是的@Xanagandr我意识到这不是你自己的代码,我很同情。有人在以你为代价炫耀,我这样说是希望其他人停止这样做。除其他事项外,它非常不可移植,并且会对Windows用户造成唾沫。@ikegami感谢您在这方面的两个输入。-l、-s、-n和-e都记录在perlruformeach$sender中。。。将$sender别名添加到foreach迭代的列表的每个元素。但是我想你可能问过%sender,它的元素是由赋值运算符+=和=.正则表达式?:login | plain匹配login和plain。有一种编写多行一行Perl程序的方式。虽然对自己这样做是可以的,就像你可以用一个字母标识符编写没有插入的代码,并且在你的私人时间里不严格使用或刷牙一样,我认为让别人接受这样的东西是非常不礼貌的。是的@Xanagandr我意识到这不是你自己的代码,我很同情。有人在以你为代价炫耀,我这样说是希望其他人停止这样做。除其他事项外,它非常不可移植,并且会对Windows用户产生唾沫。@ikegami感谢这两方面的投入。@mob:谢谢。我离任何类型的命令行都不远,也不能确定是否会扩展。在我看来,整个事情似乎有点不对劲。regex模式以$today开头,这是未定义的。在那之后,任何东西都不能正常工作。$today是由perl-s设置的…--今天=$date%F@mob非常感谢你的回答。我能感觉到我通过缩进更好地理解了这段代码。谢谢!我不知道这是怎么解释的。例如,您将-l替换为BEGIN{$/=\n;$\=\n;},这更为神秘。你也不包括-s、:login | plain或$sender,尽管这是OP提出的三个问题@暴民:谢谢你。我离任何类型的命令行都不远,也不能确定是否会扩展。在我看来,整个事情似乎有点不对劲。regex模式以$today开头,这是未定义的。在那之后,任何东西都不能正常工作。$today是由perl-s设置的…--今天=$date%F@mob非常感谢你的回答。我能感觉到我通过缩进更好地理解了这段代码。谢谢!我不知道这是怎么解释的。例如,您将-l替换为BEGIN{$/=\n;$\=\n;},这更为神秘。你也不包括-s、:login | plain或$sender,尽管这是OP提出的三个问题!我不知道,但是对于Perl初学者来说,有一些宝贵的信息。我很感谢您的努力。我不知道,但是对于Perl初学者来说,这里有一些宝贵的信息。我感谢你的努力。