解决疯狂的正则表达式,以及Stackoverflow的讽刺答案(2019)

2021-05-10 07:41:14

Stackoverflow的这种昭答案已达到MEME状态。问题是使用正则表达式在XHTML中查找开放标签,并且答案使其充分明确表示这是不可能的 - 如果您尝试,您肯定会发疯。

答案是热闹的,是有史以来最受增长的答案之一。不幸的是,这也是错误的。它是非常可能的,甚至没有那么困难:

(#匹配XHTML中的所有标记,但仅捕获打开标签<! - 。*? - >#评论|<!\ [cdata \ [。*。* \] \]>#cdata部分|>#cdata部分|> #cdata部分|< !doctype(" [^""] *"" |' [^'] *' | [ ^> /'""])*> |< \?< \?>#xml声明或处理指令|< \ w +("& #34; [^""] *"" |' [^'] *' | [^> /' ""])* />#自闭标签|<(x< \ w +)("" [^"" ] *"" |' [^'] *' | [^> /'""])*> #开立标签 - 捕获|< / \ w + s *>#结束标签)

授予,这不仅仅是一个单行,但如果你知道如何阅读正则表达式,它很简单地理解。

不仅可以用正则表达式解决任务 - 正则表达式基本上是解决问题的唯一实用方法。这就是为什么没有一个聪明的答案实际上表明了另一种解决问题的方法。

那么为什么许多答案声称它是不可能的? (甚至在解雇和嘲笑问员甚至试图试图这样一个明显愚蠢的任务时甚至感到有理由?认真,阅读一些答案。你们屈尊削减。)

其中一个答案尝试了这种令人印象深刻的声音解释:"这里的缺陷是HTML是乔姆斯基类型2语法(上下文免费语法),正则表达式是乔姆斯基类型3语法(常规语法)。由于2型语法根本更复杂,而不是3型语法(见Chomsky层次结构),您可以' T可能会使这项工作"

这一切都归功于广泛的误解,关于竞争且不可能的正则表达式。

正则表达式使用字符模式来匹配字符串中的子字符串。这些模式非常灵活,强大,但它们有一个重要的限制:它们不能递归。

让我们说你有这个字符串"(())"而且你想找到匹配的括号对。您无法编写匹配"(())"但不是"(()"嗯,如果您只需要匹配特定的嵌套深度,那么但是,您无法编写与任何深度匹配的正则表达式。因为开始和结束括号之间的模式与整个模式相同。

(如果您曾经想过为什么许多语言没有允许嵌套评论,这是解释。然后可以轻松地用一个正则表达式剥离注释。嵌套评论将更复杂。)

对于XHTML,这意味着您可以识别单个语法单位,如注释,起始标签,结束标记等。但是您不能单独使用正则表达式匹配启动标记到结束标记,因为元素可以是任意深度的元素。

当然,您可以很容易地通过将匹配与计数器或堆栈的正则表达式匹配来解决匹配。但是,你没有使用正则表达式,你已经冒险进入解析。

解析意味着将一串字符转换为某种树,其中节点在输入中表示有意义的单位。在DOM中,节点表示元素,属性,文本节点和与文档类似的元素。

解析通常使用(至少)两个步骤:授权,它使用正则表达式将输入字符串拆分为语法元素序列(数字,引用字符串,关键字,括号等),并解析令牌并构建该序列的解析树结构从它,使用堆栈或某种形式的递归来匹配递归结构。

解析器通常会从语法中丢弃无关紧要的信息。例如,空元素< x>< / x>和一个自闭标签< x />不是语义意义,因此DOM不代表该信息。

因此,您无法使用解析器来解决问题中的问题。 (至少不是标准DOM解析器 - 可能有一些可用的XHTML解析器会公开这一点,但答案都没有提供任何示例。)

在一般的stackoverflow是一个很大的资源,但这是投票系统意味着模因和货物邪教信仰赢得合法和有用的答案的一个例子,这有助于传播错误信息和混乱。