html - Perl 正则表达式仅向前解析;不是从头到尾

标签 html regex perl

用正则表达式解析 HTML 是个坏主意,但它似乎适合这种情况。

描述:给定一个 .html 文件,我必须解析内部链接,提取缩进级别、链接文本和它所在的页码到外部 .txt 文件,然后传递给其他人。

给定这个示例 HTML:

<TR valign="bottom">
    <TD valign="top"><DIV style="margin-left:0px; text-indent:-0px"><A href="#101"><FONT style="font-variant:small-caps;">The &#147;Offering&#147;</FONT>
</A></DIV></TD>
    <TD>&nbsp;</TD>
    <TD nowrap align="right" valign="top">&nbsp;</TD>
    <TD align="right" valign="top">1</TD>
    <TD nowrap valign="top">&nbsp;</TD>
</TR>
<TR valign="bottom">
    <TD valign="top"><DIV style="margin-left:15px; text-indent:-0px"><A href="#102">Sales &#038; Property
</A></DIV></TD>
    <TD>&nbsp;</TD>
    <TD nowrap align="right" valign="top">&nbsp;</TD>
    <TD align="right" valign="top">2</TD>
    <TD nowrap valign="top">&nbsp;</TD>
</TR>

外部文件将产生:

0|The "Offering"|4
15|Sales & Property|5

(页码不同,因为它们是实际页码,而不是作品集引用)。

除了 1 部分,我已经弄清楚了,当链接的文本包含额外的 HTML 代码时,比如 <Font>在第一个链接中标记。

这是我提取链接的正则表达式(注意 $string 包含上面的 html):

while ($string =~ m/<DIV style="margin-left:([0-9]+)px; text-indent:[-0-9]+px"><A href="#([0-9]+)">([a-zA-Z0-9\.,:;&#\s]+)<\/A>/gi) {
    push(@indents,$1);
    push(@linkIDs,$2);
    push(@names,escapeHTML($3));
};

这将正确提取第二个,但不是第一个,因为 HTML 代码中有 >< 和其他符号。

如果我将最后一个捕获组更改为 .+.* ,我得到了整个 HTML 文件(好吧,在第一个 <Div><A> 和最后一个 </A> 之间。似乎模式是从开头开始的,但是从文件末尾向后匹配。

这是在线正则表达式构建器的链接:http://regexr.com?2s0po
它正确地找到了我需要的东西,但在 Perl 中我没有得到相同的结果(只是提到的整个文件)。

我似乎无法写出任何能够正确捕获每个组的内容 - 你会认为“光标”会向前移动并停在第一个 </A> 处它从文件的开头看到。

任何帮助或意见或指导将不胜感激。 -谢谢。

最佳答案

在解析 HTML 或类似结构时,您必须小心使用正则表达式。您尝试的正则表达式有两个问题:

  1. 嵌套标签(第一个条目中的字体标签)
  2. 换行符(在第一个结束 anchor 标记之前)

这是处理这些问题的正则表达式:

use HTML::Entities;
while ($string =~ m/<DIV style="margin-left:([0-9]+)px; text-indent:[-0-9]+px"><A href="#([0-9]+)">(.*?)<\/A>/gis) {
    my $indent = $1;
    my $page = $2;
    (my $name = $3) =~ s/\s+$//;
    $name =~ s/^\s+//;
    $name =~ s/<.*?>//g;
    print $indent, '|', decode_entities($name), '|', $page, "\n";
}

关于html - Perl 正则表达式仅向前解析;不是从头到尾,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3535919/

相关文章:

regex - 在 Perl 中的条件之后计算正则表达式中的字符串

html - 如何将页面分成 4 个相等的部分?

javascript - Jquery 脚本不触发

python - 正则表达式查找一个或多个字符,包括中间带有句号、撇号或连字符的字符。如果最后一个符号仅在末尾出现一次,则没有最后一个符号

C# 检查 Regex 是否匹配,返回 True 而不是 False

c# - 在 C# 中使用 WebClient 有没有办法在重定向后获取站点的 URL?

apache - 如何在apache服务器上运行cgi脚本

perl - 为什么是 Perl 的 $?为 fork 进程的退出代码返回错误的值?

html - 如何更改 Angular 10 中的 body 标签类(最佳实践)?

html - AngularJS - ng-repeat 在数据不可用时显示空单元格