我正在尝试使用perl正则表达式解析“错误的html”来修复它。
错误的html如下:<p>foo<p>bar</p>foo</p>
我希望perl正则表达式返回:<p>foo<p>
我尝试了类似的内容:'|(<p\b[^>]*>(?!</p>)*?<p[^>]*>)|'
没有成功因为我不能重复(?!</p>)*?
在Perl Regex中有没有办法说出除了以下序列之外的所有charactère(在我的情况下为</p>
)
答案 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::Tidy或HTML::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 -->