8

首先,我什么也做不了,只能参考我认为有史以来最著名的 SO 帖子:

RegEx 匹配打开的标签,XHTML 自包含标签除外

现在,它甚至是 StackOverflow 的问题吗?我不知道,但我会尝试...

我从个人角度讲。虽然我从来没有这样做过,但我知道在我必须解析 HTML 的那一天,我肯定不会使用正则表达式;我会尝试找到一个 HTML 解析库。美好的。

但我不知道为什么。

有一次,我决定在 Java 中进行 CSS 验证。我“凭胆量”知道正则表达式不会削减它,所以我使用了Parboiled

我不知道为什么。

“为什么”困扰着我。我根本不是正则表达式的新手。我只是无法在正则表达式引擎可以做什么和不能做什么之间划清界限。

我的问题如下:这条明确的界限是什么?输入的什么基本特征必须存在,以便在数学上证明任何正则表达式引擎都不能可靠地确定成功和失败?

您能否给出一个简单的理论输入,该输入会导致正则表达式引擎无法给出可靠的“匹配/不匹配”答案?如果是,这种输入的定义特征是什么?

编辑为了这个讨论,我将添加一个由 SO 上的帖子建议的任务(我目前找不到链接,抱歉),它比 HTML 更简单,但我不会使用正则表达式:shell 命令行解析。

就外壳而言,它们是等效的:

alias ll="ls -l"
alias ll=ls\ -l
alias l"l"=ls' -'l
"alia"s l"l= "ls\ -l

Shell 引用机制如此之多,以至于在这种情况下我将只创建一个 Parboiled 语法……但这“出乎我的意料”。因为我发现它可能更容易......但这并不能证明这对于正则表达式是不可行的。

4

4 回答 4

6

正则表达式可以确定正则语言。但 HTML 不是常规语言。它是一种上下文无关的语言。上下文无关语言是常规语言的超集。

基本上任何可以包含递归元素的语言都是不规则的。正则语言必须是“扁平的”,所以不能有嵌套。例如,在 HTML 中,一个<div>可以嵌套在另一个内部,并且它们可以嵌套的深度没有限制。这是正则表达式无法处理的一般嵌套类型。

于 2013-06-11T22:41:36.167 回答
3

正则表达式主要用于将给定模式与输入字符串匹配,并查看是否成功。这是他们的首要目标。RE 库提供附加功能,例如根据匹配获取输入字符串的子部分,但这仅适用于少数部分。如果您需要输入的完整表示,则需要一个解析树。每个解析器都可以轻松地为您生成此文件,因为这是他们的任务之一。使用 RE,您也必须手动执行此操作。

如果您使用正则表达式,另一点是表达式的复杂性。很难测试错误,你大多得到全部或没有,要么它成功匹配(并且你得到你想要的信息),要么你什么也没得到,不得不找出它有什么问题。使用解析器生成器,您可以交互式地构建语法以获取越来越多的信息,更不用说您可能已经为每个相关的解析器找到了 HTML 语法。

最后,不要忘记对无效输入的反馈。使用 RE,您将一无所获。使用解析器,您会收到指向实际问题的错误消息。一些解析器(如由 ANTLR 生成的解析器)甚至可以处理简单的语法错误并仍然为您生成可用的解析树。

于 2013-06-13T11:54:49.773 回答
1

您说您听说过正则表达式无法解析 HTML。这是误导性的:术语有歧义。

最初,术语“正则表达式”具有特定的数学含义。自然,编程语言发明了正则表达式引擎。但随着时间的推移,这些引擎的功能越来越强大(反向引用、环视、递归模式……)。原始的“常规语言”不再是正则表达式引擎可识别的唯一语言。

例如,/^(a*)b\1$/识别字符串b, aba, aabaa,aaabaaa等;这不是常规语言。

如果你真的想的话,我认为你可以编写一个正则表达式来测试 HTML 的有效性。(你没有。)在实践中,无论你使用什么语言,都会有一个库,但正则表达式可能更容易,具体取决于你的用例。

于 2013-06-13T20:32:30.750 回答
0

我认为你能在这里得到的最好答案是一句古老的格言:“当你只有一把锤子时,整个世界看起来就像一颗钉子。” 正则表达式几乎可以做任何事情。他们的力量在于他们使用任何弦乐的能力。但是,仅仅因为您可以使用某些东西并不意味着您应该使用。正则表达式很慢,而且效率很低(您可以通过多种方式优化它们,但很少有人知道这些技术,甚至更少人真正花时间实现它们并彻底测试和检查它们的正则表达式)。

对于 HTML,有更好的工具。比正则表达式更快且更适合使用 HTML 的工具(能够构建节点树等)。与其说你不应该使用正则表达式来解析 HTML,不如说有更好的工具。当您可以使用链锯时,您为什么要尝试用黄油刀锯树?

于 2013-06-12T19:38:38.797 回答