[][] 如何在正则表达式中解析

How is [][] parsed in regex?

本文关键字:正则表达式      更新时间:2023-09-26

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

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

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

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

   [][]
   [']'[]
   ['[']]

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

把它归结为 JavaScript 设计师的过度聪明。 他们认为[]没有任何意义(空构造,对匹配没有影响),[^]没有任何意义 - 换句话说,包括换行符在内的任何内容。 大多数其他风格都有单行/DOTALL 模式,允许.匹配换行符,但 JavaScript 没有。 相反,它[^]作为一种超级点提供。

这并没有流行起来,这也一样。 正如你所观察到的,它与其他口味完全不兼容。 其他人的态度是,左括号后面的右括号应被视为文字字符。 而且,由于字符类不能嵌套(传统上),因此括号在内部永远不会具有特殊含义。 因此,[][]只是匹配方括号的紧凑方式。

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

当爪哇跳进去时,池塘变得更加浑浊。 它引入了集合交集功能,因此您可以使用例如[a-z&&[^aeiou]]来匹配辅音(范围az的字符集,与所有不aeiou字符的集合相交)。 但是,[不必在&&之后才具有特殊意义; [[a-z]&&[^aeiou]]与以前的正则表达式相同。

这意味着,在 Java 中,您始终必须使用反斜杠对字符类中的左括号进行转义,但您仍然可以通过将其放在首位来转义右括号。 因此,在 Java 中匹配方括号的最紧凑方法是 []'[] 。 我觉得这既令人困惑又丑陋,所以我经常跳过这两个括号,至少在 Java 和 JavaScript 中是这样。

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