我目前正致力于构建一个正则表达式,它将能够提取访问网站的机器人的使用者名称。到目前为止,我已经能够使表达式匹配,但它不会返回我期望的值。请查看以下示例:
#!/usr/bin/perl
use strict; use warnings;
while (<>)
{
#Remove any unseen whitespace
chomp($_);
my $i = 0;
#Open every file in turn
open(my $domlog, "<", "$_") or die "cannot open file: $!";
#these were used for testing the open/closing of files
#print "Opened $_";
#print "Closed $_";
#for now confirm the file I'm searching through
print "Opened $_\n";
#Adding the name of the domain to the @domaind array for data processing later
push (@domain, $2) if $_ =~ m/(\/usr\/local\/apache\/domlogs\/.*\/)(.*)/;
#search through the currently opened domlog line by line
while (<$domlog>) {
#clear white space again
chomp $_;
#Print the the record in full, then print the IP address of the visitor and what should be the useragent name
print "$_\n";
print "$1\n $2\n\n" if $_ =~ m/^(\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3})\s(.*)\s.*(\w+[crawl|bot|spider|yahoo|bing|google])?/i;
}
close $domlog;
}
我不确定我的正则表达式是否过于贪婪,或者我是否错误地使用了通配符。任何意见,将不胜感激。谢谢。
我完全忘记了输入,因为我担心这里的代码,我在我的服务器上的一些domlog上运行脚本,这里有一些输出以及我从中得到的东西。
输入
188.165.15.208 - - [13 / Jan / 2015:09:20:49 -0500]“GET /?page_id = 2 HTTP / 1.1”200 10574“ - ”“Mozilla / 5.0(兼容; AhrefsBot / 5.0; + {{ 3}})“
输出
188.165.15.208
- [13 / Jan / 2015:09:20:49 -0500]“GET /?page_id = 2 HTTP / 1.1”200 10574“ - ”“Mozilla / 5.0(兼容; AhrefsBot / 5.0;
输入
180.76.4.26 - - [13 / Jan / 2015:10:16:24 -0500]“GET / HTTP / 1.1”200 8744“ - ”“Mozilla / 4.0(兼容; MSIE 7.0; Windows NT 6.0)”
输出
180.76.4.26
- [13 / Jan / 2015:10:16:24 -0500]“GET / HTTP / 1.1”200 8744“ - ”“Mozilla / 4.0(兼容; MSIE 7.0; Windows NT
答案 0 :(得分:1)
如果没有示例预期输出,我只会打开猜测您可能希望实现的目标。但是有一些事情要指出你的脚本:
push (@domain, $2) if $_ =~ m/(\/usr\/local\/apache\/domlogs\/.*\/)(.*)/;
您已经在使用m
运算符,您可以使用它来更改分隔符。此外,还有(?:…)
不匹配的群组,但在这种情况下,您甚至不需要这样做。裸露的正则表达式始终与$_
匹配,如果它们不与=~
一起使用,那么您可以摆脱它。在列表上下文中,他们返回匹配组的内容。现在全部合并:
push @domain, m~/usr/local/apache/domlogs/.*/(.*)~;
现在开始你的另一个表达。如果事情变得复杂,你应该使用/x
标志,它会以很好的方式提高可读性。
.
是正则表达式中的特殊字符,它匹配任何内容,因此您可能想要逃避它。此外,对于ip-address匹配,您可以使用(?:…)
:
(\d{1,3}(?:\.\d{1,3}){3})
[…]
匹配广告中的字符,以便
[crawl|bot|spider|yahoo|bing|google]`
可以缩减为
[abcdeghilnoprstwy|]
并会做同样的事情,这显然不是你想要的,但强调,你出错了。您可能想要的是一个不匹配的组。如果您将其设为可选项,则可能不匹配(因此请在组后删除?
)。
(?:crawl|bot|spider|yahoo|bing|google)
所以这就是这个魔鬼可能看起来的结合:
if (/^(\d{1,3}(?:\.\d{1,3}){3}) # $1 - ip address
\s(.*)\s* # $2 - within spaces
(\w*(?:crawl|bot|spider|yahoo|bing|google)) # $3 - some bot string
/xi){ # end of regex
print ("$1\n$2\n$3\n");
}
可能仍然不是你想要的,但我不知道那是什么。您可能希望为$2
非贪婪(.*?)
制作论坛。如果你想在它们内部匹配,也可以逃避一些括号。
最后,看看loghack,因为有人可能已经为你完成了这项工作。
以下是相关的文档(这些是perldoc
页面,因此如果您的系统上安装了perldoc
,您也可以执行perldoc perlretut
):