您能否提供一些示例,说明为什么用正则表达式很难解析XML和HTML?\[关闭\]

HTML

Itachi十三Stafan

2020-03-23

一个错误我看到人们做,并再次试图解析XML或HTML用正则表达式。以下是难以解析XML和HTML的一些原因:

人们希望将文件视为一系列行,但这是有效的:

<tag
attr="5"
/>

人们希望将<或<tag视为标签的开头,但是类似的东西却普遍存在:

<img src="imgtag.gif" alt="<img>" />

人们通常希望将开始标签与结束标签匹配,但是XML和HTML允许标签包含它们自己(传统的正则表达式根本无法处理):

<span id="outer"><span id="inner">foo</span></span> 

人们通常希望将其与文档内容进行匹配(例如著名的“在给定页面上查找所有电话号码”问题),但是数据可能会被标记(即使在查看时看起来很正常):

<span class="phonenum">(<span class="area code">703</span>)
<span class="prefix">348</span>-<span class="linenum">3020</span></span>

注释可能包含格式不正确或不完整的标签:

<a href="foo">foo</a>
<!-- FIXME:
    <a href="
-->
<a href="bar">bar</a>

您还知道其他哪些陷阱?

第2642篇《您能否提供一些示例,说明为什么用正则表达式很难解析XML和HTML?\[关闭\]》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

10个回答
卡卡西理查德 2020.03.23

在这里对这个问题给出了简化的答案虽然它不占100%的标记,但我解释了如果您愿意做一些预处理工作是怎么可能的。

Tony番长L 2020.03.23

一般来说,由于XML语法绝非常规,因此无法使用正则表达式来解析XML。简而言之,正则表达式无法计数(嗯,Perl正则表达式实际上可以计数),因此您无法平衡开闭标记。

我不同意。如果要在正则表达式中使用递归,则可以轻松找到打开和关闭标签。

在这里,我展示了正则表达式的示例,以避免解析第一条消息中的示例错误。

老丝阿飞 2020.03.23

我认为问题可以归结为:

  1. 正则表达式几乎总是错误的。存在合法输入,它将无法正确匹配。如果您足够努力,则可以使它达到99%正确或99.999%的正确性,但是几乎不可能使它达到100%的正确性,仅是因为XML使用实体允许的怪异事物。

  2. 如果正则表达式不正确(即使对于0.00001%的输入),则您会遇到安全问题,因为有人可以发现一个输入会破坏您的应用程序。

  3. 如果正则表达式足够正确,可以覆盖99.99%的情况,那么它将完全无法阅读和维护。

  4. 正则表达式很可能在中等大小的输入文件上表现很差。我与XML的第一次接触是用一个正确的XML解析器替换一个Perl脚本(不正确地)解析传入的XML文档,我们不仅用300行可读代码替换了300行任何人都可以理解的代码,而且还改善了用户响应时间从10秒到大约0.1秒。

番长猴子 2020.03.23

我相信这本 经典的书可以为您提供所需的信息。您可以在其中的注释之一中找到要点:

我认为这里的缺陷是HTML是Chomsky Type 2语法(无上下文语法),而RegEx是Chomsky Type 3语法(正则表达式)。由于类型2的语法从本质上比类型3的语法复杂-您不可能希望做到这一点但是很多人会尝试,有些人会声称成功,而另一些人会发现错误并完全把你弄糟。

来自Wikipedia的更多信息:Chomsky Hierarchy

神乐 2020.03.23

我很想说“不要重新发明轮子”。除了XML是一种非常非常复杂的格式。因此,也许我应该说“不要重新发明同步加速器”。

也许正确的陈词滥调始于“当您只有锤子...”时,您知道如何使用正则表达式,正则表达式擅长解析,那么为什么还要花时间学习XML解析库呢?

因为解析XML很困难您不必学习使用XML解析库而节省的所有工作,将远远超过您需要做的创造性工作和减少错误的数量。为了您自己的利益,google“ XML库”并利用他人的工作。

GilJinJin 2020.03.23

这取决于您“解析”的意思。一般来说,由于XML语法绝非常规,因此无法使用正则表达式来解析XML。简而言之,正则表达式无法计数(嗯,Perl正则表达式实际上可以计数),因此您无法平衡开闭标记。

老丝阿飞 2020.03.23

人们通常会默认编写贪婪模式,这通常会导致不加思索的。*将大块文件吞入最大的<foo>。* </ foo>中。

猴子 2020.03.23

人们实际上是使用正则表达式犯了一个错误,还是仅仅足以胜任他们要完成的任务?

我完全同意,无法使用正则表达式解析html和xml,因为其他人已经回答了。

但是,如果您的要求不是解析html / xml而是仅获取html / xml的“已知良好”位中的一小部分数据,那么正则表达式甚至是更简单的“子字符串”就足够了。

达蒙 2020.03.23

我写了一个关于此主题的完整博客文章:正则表达式限制

问题的症结在于HTML和XML是递归结构,需要计数机制才能正确解析。真正的正则表达式无法计数。您必须具有上下文无关的语法才能计数。

上一段带有一些警告。现在,某些正则表达式实现支持递归的想法。但是,一旦开始将递归添加到正则表达式中,您实际上就在扩展边界,应该考虑使用解析器。

猪猪 2020.03.23

不在列表中的一个陷阱是属性可以按任何顺序出现,因此,如果您的正则表达式正在查找带有href“ foo”和类“ bar”的链接,则它们可以按任意顺序出现,并且可以具有任意其他数量他们之间的事情。

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android