perl regex多个组

时间:2012-12-11 02:38:56

标签: regex perl html-parsing screen-scraping

我正在尝试在perl中进行屏幕刮擦,并将其放到一个表元素数组中。

字符串:

<tr>
        <td>10:11:00</td>
        <td><a href="/page/controller/33">712</a></td>
        <td>Start</td>
        <td>Finish</td>
        <td>200</td>
        <td>44</td>

代码:

if($item =~ /<td>(.*)?<\/td>/)
            {
                print "\t$item\n";
                print "\t1: $1\n";
                print "\t2: $2\n";
                print "\t3: $3\n";
                print "\t4: $4\n";
                print "\t5: $5\n";
                print "\t6: $6\n";
            }

输出:

1: 10:11:00
2: 
3: 
4: 
5: 
6: 

我尝试了多项但无法获得预期的结果。想法?

2 个答案:

答案 0 :(得分:5)

use strict;
use warnings;

my $item = <<EOF;
<tr>
        <td>10:11:00</td>
        <td><a href="/page/controller/33">712</a></td>
        <td>Start</td>
        <td>Finish</td>
        <td>200</td>
        <td>44</td>
EOF

if(my @v = ($item =~ /<td>(.*)<\/td>/g))
{
  print "\t$item\n";
  print "\t1: $v[0]\n";
  print "\t2: $v[1]\n";
  print "\t3: $v[2]\n";
  print "\t4: $v[3]\n";
  print "\t5: $v[4]\n";
  print "\t6: $v[5]\n";
}

if(my @v = ($item =~ /<td>(.*)<\/td>/g))
{
  print "\t$item\n";
  print "\t$_: $v[$_-1]\n" for 1..@v;
}

输出:

1: 10:11:00
2: <a href="/page/controller/33">712</a>
3: Start
4: Finish
5: 200
6: 44

答案 1 :(得分:1)

代码的行为与您告诉它完全一样。这就是:

你恰好匹配正则表达式一次。它确实匹配,并使用第一个(也是唯一的!)捕获缓冲区的值填充$1变量。匹配返回“true”,并执行if-branch中的代码。

你想做两件事:

  1. /g修饰符匹配。这是全局匹配,并尝试在字符串中返回每个匹配,而不仅仅是第一个。
  2. 在列表上下文中执行正则表达式,以便将捕获缓冲区保存到数组
  3. 这将导致以下代码:

    if ( my @matches = ($item =~ /REGEX/g) ) {
      for my $i (1 .. @matches) {
        print "$i: $matches[$i-1]\n";
      }
    }
    

    还要注意parsing HTML with regexes is evil,您应该在CPAN中搜索您喜欢的模块。