【问题标题】:How is [][] parsed in regex?[][] 如何在正则表达式中解析?
【发布时间】:2016-06-10 07:50:30
【问题描述】:

尝试简单的正则表达式我发现了一些奇怪的行为。

单对括号 [] 被视为不完整的字符类(PCRE 和 Python)并引发错误,或者被视为空字符类 (JS),这不是错误,但不匹配任何内容.

接下来,JS 按预期将[][] 视为两个空类,但在PCRE 和Python 最里面的括号][ 被解释为文字,即使它们没有被转义。

进一步的实验表明,三个表达式在实践中是等价的:

   [][]
   [\]\[]
   [\[\]]

第二个和第三个对我来说很有意义,但为什么第一个有效?有人可以向我解释一下 [][] 构造是如何解析的吗?

【问题讨论】:

  • 它会根据您使用的语言而有所不同。对于 Python,documentation 表示“要匹配集合内的文字 ']',请在其前面加上反斜杠,或将其放在集合的开头”。
  • 在哪个引擎中是如何解析的? AFAIK 不同语言使用的正则表达式并非基于真正的标准,它们主要是 Perl 的临时衍生品。如果没有标准,这个问题只能在特定语言/引擎的上下文中回答。如果您缩小范围,有人可能会深入研究语言的实现或规范,并找到负责此行为的规则。这个问题有点宽泛。

标签: javascript python regex pcre


【解决方案1】:

这归咎于 JavaScript 设计者过于聪明。他们决定[] 什么都没有(一个空结构,对匹配没有影响),[^] 意味着不是什么——换句话说,任何包括换行符。大多数其他风格都有一个单行/DOTALL 模式,允许. 匹配换行符,但 JavaScript 没有。相反,它提供[^] 作为一种超级点。

这并没有流行起来,但也一样。正如您所观察到的,它与其他口味完全不相容。其他人都认为,在左括号之后的右括号应该被视为文字字符。而且,由于字符类不能嵌套(传统上),opening 括号在其中永远没有特殊含义。因此,[][] 只是一种匹配方括号的简洁方式。

更进一步,如果您想匹配除][^ 之外的任何字符,在大多数情况下,您都可以这样写:[^][^]。取反后的右括号 ^ 被视为文字,左括号并不特殊,第二个 ^ 也被视为文字。但是在 JavaScript 中,[^][^] 是两个独立的原子,每个原子都匹配任何字符(包括换行符)。要获得与其他风味相同的含义,您必须转义第一个右括号:[^\][^]

当 Java 介入时,池塘变得更加泥泞。它引入了 set intersection 功能,因此您可以使用,例如,[a-z&&[^aeiou]] 来匹配辅音(@ 范围内的字符集987654335@ 到 z,与不是 aeiou 的所有字符集相交。但是,[ 不必紧跟在&& 之后才具有特殊含义; [[a-z]&&[^aeiou]] 与前面的正则表达式相同。

这意味着,在 Java 中,您总是必须在字符类中使用反斜杠来转义左括号,但您仍然可以通过将右括号放在首位来转义。所以在 Java 中匹配方括号最简洁的方式是[]\[]。我觉得这令人困惑和丑陋,所以我经常避开这两个括号,至少在 Java 和 JavaScript 中是这样。

.NET 有一个类似的功能,称为 set subtraction,它更简单并且使用更严格的语法:[a-z--[aeiou]]。嵌套类只能出现在-- 之后,并且整个构造必须位于封闭字符类的末尾。您仍然可以在 .NET 中使用 [][] 匹配方括号。

【讨论】:

    猜你喜欢
    • 2015-04-24
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 2012-10-17
    • 1970-01-01
    • 2011-03-20
    • 2012-07-08
    相关资源
    最近更新 更多