如何使用Perl Regex在另一个</p> <p> </p>中检测<p>

时间:2011-02-18 12:03:08

标签: regex perl html-parsing

我正在尝试使用perl正则表达式解析“错误的html”来修复它。 错误的html如下:<p>foo<p>bar</p>foo</p>

我希望perl正则表达式返回:<p>foo<p>

我尝试了类似的内容:'|(<p\b[^>]*>(?!</p>)*?<p[^>]*>)|' 没有成功因为我不能重复(?!</p>)*?

在Perl Regex中有没有办法说出除了以下序列之外的所有charactère(在我的情况下为</p>

5 个答案:

答案 0 :(得分:1)

尝试类似:

<p>(?:(?!</?p>).)*</p>(?!(?:(?!</?p>).)*(<p>|$))

快速分解:

<p>(?:(?!</?p>).)*</p>

匹配{strong>不包含<p> ... </p><p>的{​​{1}}。部分:

</p>
向前看时{p>为“true”((?!(?:(?!</?p>).)*(<p>|$)) )没有(?! ... )或输入结束(<p>),没有任何(<p>|$)和{{1介于两者之间(<p>)。

演示:

</p>

打印:

(?:(?!</?p>).)*

请注意,此正则表达式技巧仅适用于字符串中的my $txt="<p>aaa aa a</p> <p>foo <p>bar</p> foo</p> <p> bb <p>x</p> bb</p>"; while($txt =~ m/(<p>(?:(?!<\/?p>).)*<\/p>)(?!(?:(?!<\/?p>).)*(<p>|$))/g) { print "Found: $1\n"; }

Found: <p>bar</p>
Found: <p>x</p>

<p>baz</p>不匹配!替换<p>foo <p>bar</p> <p>baz</p> foo</p> 后,您可以对输入执行第二次运行,在这种情况下<p>bar</p>将匹配。

答案 1 :(得分:1)

我同意安迪的观点。使用regexp解析非平凡的HTML是一个痛苦的世界。

仔细查看HTML :: TreeBuilder :: XPath和HTML :: DOM,以便对HTML文档进行结构更改。

答案 2 :(得分:0)

这个正则表达式:

<p>(?:(?!</p>).)*?<p>

匹配时
<p>foo<p>bar</p>foo</p>

结果

<p>foo<p>

答案 3 :(得分:0)

如果您尝试验证HTML,请考虑使用HTML::TidyHTML::Lint这样的模块。

答案 4 :(得分:0)

也许Marpa::HTML可以帮到你。阅读它在author's blog about it上的一些有趣的能力。缺点是解析器与解释器一起使用(我可能会得到一些不正确的语义),根据代码中某个逻辑位置可能存在的内容来确定应该出现的内容。

其中显示的示例解决了类似的问题,因为您似乎以比使用正则表达式更加一致的方式处理问题,而正则表达式将不可避免地受到边缘情况的影响。

Marpa::HTML附带一个命令行实用程序,使用该模块构建,名为html_fmt。这实现了一个解析引擎来修复和漂亮打印html。这是一个例子。如果'bad.html'包含<p>foo<p>bar</p>foo</p>,那么html_fmt bad.html会给出:

<!-- Following start tag is replacement for a missing one -->
<html>
  <!-- Following start tag is replacement for a missing one -->
  <head>
  </head>
  <!-- Preceding end tag is replacement for a missing one -->
  <!-- Following start tag is replacement for a missing one -->
  <body>
    <p>
      foo
    </p>
    <!-- Preceding end tag is replacement for a missing one -->
    <p>
      bar
    </p>
    foo
    <!-- Next line is cruft -->
    </p>
  </body>
  <!-- Preceding end tag is replacement for a missing one -->
</html>
<!-- Preceding end tag is replacement for a missing one -->