如何使用Perl正则表达式提取多行代码?

时间:2011-05-25 07:14:08

标签: regex perl matching multiline

我正在尝试从本网站提取所有IP地址:http://www.game-monitor.com/

我想在该页面上对IP进行正则表达式,提取所有这些并在屏幕上显示它们。

这就是我到目前为止,你能告诉我什么是错的并帮助我吗?

#!/usr/bin/perl

use HTTP::Request;
use LWP::UserAgent;

print 'Press [1] To Begin: ';
chomp ($begin = <STDIN>);

my $url = 'http://www.game-monitor.com/';
my @ips = ('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}','\d{1,3}\.\d{1,2}\.\d{1,3}\.\d{1,2}','\d{1,2}   \.\d{1,3}\.\d{1,2}\.\d{1,3}','\d{1,2}\.\d{1,2}\.\d{1,2}\.\d{1,3}','\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,2}','\d{1,3}\.\d{1,3}\.\d{1,2}\.\d{1,2}','\d{1,2}\.\d{1,2}\.\d{1,3}\.\d{1,3}','\d{1,2}\.\d{1,2}\.\d{1,2}\.\d{1,2}','\d{1,2}\.\d{1,3}\.\d{1,3}\.\d{1,2}','\d{1,3}\.\d{1,2}\.\d{1,2}\.\d{1,3}');

if ($begin eq 1)
{
my $request = HTTP::Request->new(GET => $url);
my $useragent = LWP::UserAgent->new();
my $response = $useragent->request($request);
my $result = $response->content;

foreach $ip (@ips)
{
if ($result =~ /($ips[0])/ ||
$result =~ /($ips[1])/ ||
$result =~ /($ips[2])/ ||
$result =~ /($ips[3])/ ||
$result =~ /($ips[4])/ ||
$result =~ /($ips[5])/ ||
$result =~ /($ips[6])/ ||
$result =~ /($ips[7])/ ||
$result =~ /($ips[8])/ ||
$result =~ /($ips[9])/
)
{
    print "IP: $1 \n";
    print "IP: $2 \n";
    print "IP: $3 \n";
    print "IP: $4 \n";
    print "IP: $5 \n";
    print "IP: $6 \n";
    print "IP: $7 \n";
    print "IP: $8 \n";
    print "IP: $9 \n";
    print "IP: $10 \n";
}
}
}

4 个答案:

答案 0 :(得分:3)

为简化多行替换,请使用/s modifier,这实际上告诉Perl假装字符串是单行 - 即使它不是。

有关详细信息,请参阅perlre

如果您使用Regexp::Common::net这样的模块会很好 - 为IPv4地址提供正则表达式而不是编写自己的正则表达式来匹配IP地址。

例如尝试类似的事情,

use Regexp::Common qw/net/;
while (<>) {
  print $1, "\n" if /($RE{net}{ipv4})/;
}

答案 1 :(得分:3)

使用/g修饰符匹配所有IP。 提示:使用-w参数和strict包以避免“编码风格错误”。

#!/usr/bin/perl -w

use strict;
use HTTP::Request;
use LWP::UserAgent;

print 'Press [1] To Begin: ';
chomp (my $begin = <STDIN>);

my $url = 'http://www.game-monitor.com/';
my $ip_regex = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if ($begin eq 1)
{
    my $request = HTTP::Request->new(GET => $url);
    my $useragent = LWP::UserAgent->new();
    my $response = $useragent->request($request);
    my $result = $response->content;

    while ($result =~ /($ip_regex)/g)
    {
        print "IP: $1 \n";
    }

}

答案 2 :(得分:2)

#!/usr/bin/perl

use HTTP::Request;
use LWP::UserAgent;


my $url = 'http://www.game-monitor.com/';
my $request = HTTP::Request->new(GET => $url);
my $useragent = LWP::UserAgent->new();
my $response = $useragent->request($request);
my $result = $response->content;

@m = ($result =~ /\b(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})\b/sg);
foreach (@m) {
        print "IP: $_\n";
}

答案 3 :(得分:1)

我真的不知道你要对你的大阵列@ips做些什么。第一个正则表达式已匹配所有IP地址(因为\d{1,3}表示“一到三个数字”,它已包含具有两个数字的IP地址),因此您不需要\d{1,2}的所有这些排列。

您可以做的一件事就是使用\b字边界锚来包围您的正则表达式,以确保您不匹配123.123.123.123内的99123.123.123.12399或类似内容。此外,您可能已经意识到您的正则表达式也会匹配999.999.999.999之类的内容。如果这不是问题,因为你的输入不包含无效的IP地址,那么当然没关系。

最后,您需要/g全局修饰符,以便您的正则表达式不仅可以找到字符串中的第一个,而且还可以找到所有匹配项。

从本质上讲,如何做到这一点:

while ($result =~ m/\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g) {
    print "IP: $&\n";
}