【问题标题】:Regex - what does the infinite error mean?正则表达式 - 无限错误是什么意思?
【发布时间】:2016-03-12 14:38:33
【问题描述】:

我目前正在参加一些技术面试,我们问了一个关于检查大括号是否平衡的问题(相同数量的打开/关闭,并且关闭永远不会进行匹配的打开) - 要求人们编写一个小函数来验证这一点。

一些候选人曾考虑尝试使用正则表达式来解决这个问题,但很快就放弃了。我决定试一试,看看是否可行。我目前正在使用以下测试字符串:

通过

{(function(r){ return r; })()} {}{}{}{} {{{{}}}}

失败

}{ {{}}} {{{}}

我认为以下正则表达式可以工作[^{}]*({[^{}]*})*[^{}]*。想法是匹配非大括号字符,然后匹配 {,然后是非大括号字符,然后是 },重复括号匹配,然后以任何非大括号字符结束。

我在使用 regexr.com 时似乎收到了 infinite 错误,但我不明白为什么:

谁能解释一下到底是什么原因造成的?

【问题讨论】:

  • 在大多数正则表达式风格中,{} 需要转义(在字符类之外),因为它们是量词。
  • 我不认为 JavaScript 可以支持任意级别的嵌套。一些正则表达式风格可以(因为它们超越了标准正则表达式),但不是 JavaScript 的。你可以做一个可以处理(比如说)最多四层嵌套的表达式,但它必须是硬编码的。
  • "Finite automata can't count" - 它可能可以将平衡大括号与一些现代“正则表达式”机制相匹配,但如果它我会很惊讶JavaScript 是可能的。
  • @Pointy 使用 Javascript 他可以我们 String.replace(),搜索 {} 并在作为 replace 的第二个参数传递的函数中计算它们
  • 现代正则表达式引擎支持堆栈进行计数。在这种情况下,它将用于平衡文本。一些引擎使用递归 Perl、PCRE 等来做到这一点,一些引擎通过计数 Dot-Net 来做到这一点。大多数其他旧的、过时的引擎 Java、JavaScript 等都不会这样做。底线,平衡的文本(任何东西)可以使用现代引擎进行测试或匹配。 你的尝试肯定做不到。

标签: javascript c# regex


【解决方案1】:

您将收到一个无限错误,因为您的正则表达式可以匹配任何文本。由于您的所有组都标有*,因此它们都被认为是可选的(* 匹配零次或多次出现)。这意味着引擎可以在您的模式中找到任何组的零次出现,并且仍然认为该文本是匹配的。

考虑用+ 标记至少一个组,这意味着“一个或多个”而不是“零个或多个”。试试这个模式:

[^{}]*(\{[^{}]*\})+[^{}]*

这样,引擎有某种限制,它必须匹配您的模式才能被接受。

注意:当不在字符块 ([]) 中时,转义 {} 也是明智之举。我在上面的模式中做到了这一点。 Regexr.com 似乎并不在意,但有些引擎在没有它们的情况下可能会产生解析错误。

【讨论】:

  • 非常感谢,确实有道理。我可能需要深入了解正则表达式实现的工作原理。
【解决方案2】:

更新

这是您需要的正则表达式(一级):

\{{0,1}[^\{\}]*\{[^\{\}]*\}[^\{\}]*\}{0,1}

我不会写嵌套规则,但你可以说你需要多少层。

解释:

| - 表示替代(a|b - 从字面上匹配“a”或“b”)
^ - 表示行首(^a - 匹配任何以“a”开头的字符串,“a tax”,“apple”...)
$ - 表示行尾(a$ - 匹配任何以“a”结尾的字符串,“umbrella”)
\{ - 匹配字符:“{”字面意思
\( - 匹配字符:“(”字面意思

【讨论】:

  • 这对{hello { world } {it { is { a } nice} day}} 有用吗?这是一个仅针对样本输入的解决方案,而不是针对一般问题。
  • @Pointy:啊,我明白了——我的错误。我更正了这一点,但正则表达式不支持嵌套规则。我可以为他写更好的规则(更多级别),但我需要知道它们的数量。
  • 问题的重点不在于回答如何实现我的尝试,而在于“为什么会失败”。不过谢谢。
猜你喜欢
  • 2012-06-10
  • 1970-01-01
  • 2011-08-28
  • 1970-01-01
  • 2011-06-15
  • 2012-05-07
  • 2015-07-23
  • 2012-09-07
  • 1970-01-01
相关资源
最近更新 更多