Ruby正则表达式中递归嵌套匹配花括号对

8

我有以下字符串:

The {quick} brown fox {jumps {over {deep} the} {sfsdf0} lazy} dog {sdfsdf1 {sdfsdf2}

PHP正则表达式:

/(?=\{((?:[^{}]+|\{(?1)\})+)\})/g

它会得到以下匹配结果:
[5-10]  `quick`
[23-60] `jumps {over {deep} the} {sfsdf} lazy`
[30-45] `over {deep} the`
[36-40] `deep`
[48-54] `sfsdf0`
[76-83] `sdfsdf2`

查看:http://regex101.com/r/fD3iZ2

我正在尝试在Ruby中实现相同的功能,但我遇到了一个问题:(?1)导致未定义的组选项错误:

str = "The {quick} brown fox {jumps {over {deep} the} {sfsdf} lazy} dog {sdfsdf {sdfsdf}"
str.scan /(?=\{((?:[^{}]+|\{(?1)\})+)\})/

SyntaxError: undefined group option: /(?=\{((?:[^{}]+|\{(?1)\})+)\})/

请参见:http://fiddle.re/n6w4n

巧合的是,我在JavaScript和Python中都遇到了同样类型的错误。

我的正则表达式技能今天几乎已经用完了,非常感谢您提供帮助。


据我所知,?在JavaScript和Ruby中是括号内的保留字符。 - Qantas 94 Heavy
(?1) 在Javascript中被认为是可以接受的,它意味着递归第一个子模式。由于我在Ruby、Javascript和Python中都遇到了相同的错误,我认为问题在于括号分组,而不是?1 - Dom
哇 - 每天都能学到新东西,谢谢。我会去看看的。 - Qantas 94 Heavy
JavaScript不支持递归,Python也不支持。 - Tim Pietzcker
JavaScript完全不支持递归,除非使用正则表达式包(第三方-我以前从未使用过)。Python支持递归,但需要使用regex包,而不是re。两者都不支持捕获组递归,只支持完整模式递归。 - drizzt13
1个回答

18
Ruby使用不同的语法进行递归: \g<1> 替换了 (?1)。所以尝试使用。
(?=\{((?:[^{}]++|\{\g<1>\})++)\})

我还将量词改为所有格形式,以避免在大括号不平衡的情况下出现过度回溯。

irb(main):003:0> result = str.scan(/(?=\{((?:[^{}]++|\{\g<1>\})++)\})/)
=> [["quick"], ["jumps {over {deep} the} {sfsdf} lazy"], ["over {deep} the"], 
["deep"], ["sfsdf"], ["sdfsdf"]]

有趣的是,你上面展示的相同语法也适用于PHP。 - Dom
匹配空的花括号对 {},您可以在\g<1>后面添加?,就像这样:(?=\{((?:[^{}]++|\{\g<1>?\})++)\}) - Christian Rodemeyer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接