似乎在stackoverflow上的每个问题中,提问者使用regex从HTML中获取一些信息,将不可避免地有一个“答案”,说不要使用regex解析HTML。

为什么不呢?我知道有一些所谓的“真正的”HTML解析器,比如Beautiful Soup,我相信它们是强大而有用的,但如果您只是在做一些简单、快速或简单的事情,那么当一些正则表达式语句就可以很好地工作时,为什么要麻烦使用如此复杂的东西呢?

此外,是否只是因为我不理解正则表达式的某些基本原理,才使得它们在解析中成为一个糟糕的选择?


当前回答

我相信答案就在计算理论中。对于使用正则表达式解析的语言,根据定义必须是“regular”(链接)。HTML不是常规语言,因为它不符合常规语言的许多标准(与HTML代码中固有的多层嵌套有很大关系)。如果你对计算理论感兴趣,我推荐这本书。

其他回答

正则表达式并不是为处理嵌套的标记结构而设计的,要处理真正HTML中可能出现的所有边缘情况,往好里说是复杂的(往坏里说是不可能的)。

两个简单的原因:

编写一个能够抵御恶意输入的正则表达式是困难的;比使用预先构建的工具难多了 编写一个正则表达式来处理你不可避免地会遇到的荒谬的标记是困难的;比使用预先构建的工具难多了

关于正则表达式在解析中的适用性:它们并不合适。您是否见过解析大多数语言所需的正则表达式类型?

正则表达式无法解析整个HTML,因为它依赖于匹配开始标记和结束标记,而正则表达式则无法匹配。

正则表达式只能匹配常规语言,但HTML是一种与上下文无关的语言,而不是常规语言(正如@StefanPochmann所指出的,常规语言也是与上下文无关的,因此与上下文无关并不一定意味着不常规)。在HTML上使用regexp唯一能做的事情是启发式,但这并不适用于所有条件。任何正则表达式都可以错误地匹配HTML文件。

Actually, HTML parsing with regex is perfectly possible in PHP. You just have to parse the whole string backwards using strrpos to find < and repeat the regex from there using ungreedy specifiers each time to get over nested tags. Not fancy and terribly slow on large things, but I used it for my own personal template editor for my website. I wasn't actually parsing HTML, but a few custom tags I made for querying database entries to display tables of data (my <#if()> tag could highlight special entries this way). I wasn't prepared to go for an XML parser on just a couple of self created tags (with very non-XML data within them) here and there.

所以,即使这个问题已经死了,它仍然会出现在谷歌搜索中。我读了它,并认为“接受挑战”,并完成了修复我的简单代码,而不需要替换所有东西。决定给有类似理由的人提供不同的意见。最后一个答案是4小时前发布的,所以这仍然是一个热门话题。

因为有很多方法可以“搞砸”HTML,浏览器会以一种相当自由的方式对待它们,但要用正则表达式重现浏览器的自由行为来覆盖所有情况需要相当大的努力,所以你的正则表达式将不可避免地在某些特殊情况下失败,这可能会在你的系统中引入严重的安全漏洞。