解释和修改Perl一行程序?
我在网上找到了以下Perl“one liner”脚本,所以不是我的:解释和修改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 -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初学者来说,这里有一些宝贵的信息。我感谢你的努力。