如何匹配特定标签值并在匹配后从前一个标签获取结果?

时间:2012-05-20 08:12:33

标签: regex perl

输入文件:

<TABLE BORDER="7" CELLPADDING="10">
<TR>
<TD>This is a TD cell</TD>
<TD><PRE> sample</PRE></TD>
<TH>This is a TH cell</TH>
</TR>
<TR>
<TH VALIGN="TOP">Text aligned top</TH>
<TH>Image in TH cell with default alignments ---></TH>
<TH><IMG SRC="blylplne.gif" ALT="airplane"></TH>
</TR>
</TABLE>

我想匹配标记<TD><PRE> sample</PRE></TD>,如果匹配,我想从前一个标记<TD>This is a TD cell</TD>获得结果

输出:

  

这是一个TD小区

我尝试使用以下代码:

MY $Output = m/<TD.*?\/TD>/;

我能够匹配标签,但无法通过匹配相同的标签来获取前一个标签的结果。任何人都可以使用它。 提前谢谢。

4 个答案:

答案 0 :(得分:1)

由于你需要倒退,我认为可能需要构建一个完整的树。通常我建议使用DOM样式的HTML解析器(请参阅Mojo::DOM),但是要构建树,请尝试HTML::Tree之类的内容。

编辑:

所以我决定看看我是否可以用Mojo::DOM做到这一点,而且效果很好:

#!/usr/bin/env perl

use strict;
use warnings;

use 5.10.0;
use Mojo::DOM;

my $dom = Mojo::DOM->new->xml(1)->parse(<<'HTML');
<TABLE BORDER="7" CELLPADDING="10">
<TR>
<TD>This is a TD cell</TD>
<TD><PRE> sample</PRE></TD>
<TH>This is a TH cell</TH>
</TR>
<TR>
<TH VALIGN="TOP">Text aligned top</TH>
<TH>Image in TH cell with default alignments ---></TH>
<TH><IMG SRC="blylplne.gif" ALT="airplane"></TH>
</TR>
</TABLE>
HTML

my $collection = $dom->find('TR TD');
my $i = -1; # so that first increment makes 0
$collection->first(sub{$i++; /sample/;});
say $collection->[$i-1];

你必须强制进行XML解析,因为HTML5不使用大写标签,但其余部分应该是自我解释的。

编辑2012年11月1日

Mojolicious 3.54刚刚发布,它为Mojo :: DOM提供了新的nextprevious方法,这对我们有帮助。 (我使用这篇文章作为他们使用的案例)。这意味着,现在你可以做到:

say $dom->find('TR TD')->first(qr/sample/)->previous;

而不是上面例子的最后4行。

答案 1 :(得分:0)

对于正则表达式来说,这不是一个好问题。使用单个表达式可以做的最好的事情是匹配两个单元格并捕获组中第一个单元格的内容。例如

<TD>(.*?)</TD>\s*<TD><PRE> sample</PRE></TD>

我猜你需要用另一个表达式替换<PRE> sample</PRE>所有的内容,但是你没有在这里提供足够的信息。

如果您需要更一般地执行此操作,使用可以实际遍历文档树的html解析器将是更好的选择。

答案 2 :(得分:0)

你可以使用lookbehind和lookahead断言文本在另一个文本之前或之后 - 看起来是零宽度断言,这意味着它们不捕获任何东西:

(?<=TD>)[^>]+(?=</TD>\s*<TD><PRE>\s*sample</PRE></TD>)

表示:

  1. (?<=TD>) - 从你所在的位置看后面,断言有一个标签
  2. [^>]+ - 匹配不是标记结尾的所有内容
  3. (?=</TD>\s*<TD><PRE>\s*sample</PRE></TD>) - 从您所在的位置向前看,并声明以下文字为</TD>\s*<TD><PRE>\s*sample</PRE></TD>(结束标记,可选的空格字符和您的条件)
  4. 此匹配的结果是#2匹配的文本。

答案 3 :(得分:0)

虽然我们经常被警告不要使用成熟的HTML解析器编写我们自己的html正则表达式,但有时前者可能会完成这项工作。看看此选项是否有帮助(您可能希望匹配<PRE>标签的更多内容):

use Modern::Perl;

my $html = <<'html';
<TABLE BORDER="7" CELLPADDING="10">
<TR>
<TD>This is a TD cell</TD>
<TD><PRE> sample</PRE></TD>
<TH>This is a TH cell</TH>
</TR>
<TR>
<TH VALIGN="TOP">Text aligned top</TH>
<TH>Image in TH cell with default alignments ---></TH>
<TH><IMG SRC="blylplne.gif" ALT="airplane"></TH>
</TR>
</TABLE>
html

say $html =~ m|<TD>(.*?)</TD>.*<TD><PRE>|is;

<强>输出

这是一个TD小区