【问题标题】:Match the last group of (potentially) nested brackets匹配最后一组(可能)嵌套括号
【发布时间】:2014-08-02 03:38:47
【问题描述】:

我想匹配 last 组,该组包含在 [] 中,但在嵌套结构中可能包含多个 [] 中的一个。

我设法使用 pythonregex 进行嵌套的 [] 匹配,虽然并不优雅。此解决方案适用于某些情况(例如s1),但不适用于s2s3,当有多个此类匹配时。我的解决方案只会匹配第一个。

有什么建议吗?更好的正则表达式?还是正则表达式不是要走的路?非常感谢!

In [116]:

s1 = 'AAA [BBB [CCC]]'
s2 = 'AAA [DDD] [EEE]'
s3 = 'AAA [BBB [CCC]] [EEE]'

for s in [s1, s2, s3]:
    result = regex.search(r'(?<rec>\[(?:[^\[\]]++|(?&rec))*\])',s,flags=regex.VERBOSE)
    print(result.captures('rec'))
['[CCC]', '[BBB [CCC]]'] #I know it is perfect, but I can take the last one in the list
['[DDD]'] #This is the first one, I want the last one, which is [EEE]
['[CCC]', '[BBB [CCC]]'] #same problem as above

编辑:

非常感谢您的帮助,如果我有 15 个代表,我会投票给你们所有人。但是,很抱歉没有包括预期的结果,应该是:

'AAA [BBB [CCC]]' -> '[BBB [CCC]]'
'AAA [DDD] [EEE]' -> '[EEE]'
'AAA [BBB [CCC]] [EEE]' -> '[EEE]'
'000 [[aaa] xxx [yyy [zzz ]]' -> '[[aaa] xxx [yyy [zzz ]]'

【问题讨论】:

  • 您实际上可以通过前瞻/后视来完成此操作,但是在这种情况下,我可能会使用堆栈/解析器。
  • @Vlad,他有一个嵌套结构。这可能就是他在这里使用递归正则表达式的原因,我不确定单独环顾四周是否可行,但如果我错了,请纠正我。欢迎来到 SO,OP!
  • 你想要什么输出?
  • [[aaa] xxx [yyy [zzz ]] 是一种可能的情况吗?即不同层次的嵌套结构的混合。
  • 仅供参考添加了经过测试的 Python 代码。 :)

标签: python regex python-2.7


【解决方案1】:

在 Python 中,要使用递归或重复子例程,我们需要使用 Matthew Barnett 出色的 regex 模块...而且,正如 @CTZhu 指出的那样,您已经在使用它了!

要明确术语,“嵌套”可以有几种理解,如:

  1. 简单嵌套,如[C[D[E]F]],它是...的子集
  2. 更复杂的家庭式嵌套,如[B[C] [D] [E[F][G]]]

您需要能够处理后者,而这个简短的正则表达式为我们做到了:

\[(?:[^[\]]++|(?R))*\]

这将匹配所有嵌套的大括号。现在我们需要做的就是打印最后一个匹配项。

这是一些经过测试的 Python 代码:

import regex # say "yeah!" for Matthew Barnett
pattern = r'\[(?:[^[\]]++|(?R))*\]'
myregex = regex.compile(pattern)

# this outputs [EEE]
matches = myregex.findall('AAA [BBB [CCC]] [EEE]')
print (matches[-1])

# this outputs [C[D[E]F]] (simple nesting)
matches = myregex.findall('AAA [BBB] [C[D[E]F]]')
print (matches[-1])

# this outputs [B[C] [D] [E[F][G]]] (family-style nesting)
matches = myregex.findall('AAA [AAA] [B[]B[B]] [B[C] [D] [E[F][G]]]')
print (matches[-1])

【讨论】:

  • +1 表示(我认为的)正确答案。但是您错过了 OP 已经在使用 regex 的事实,请参阅 regex.search?干杯!
  • 感谢您的完美解决方案!我将研究您提供的演示以更好地理解它。
  • @CTZhu 谢谢,没注意到!为更复杂的嵌套添加了正则表达式,例如 [B[C] [D] [E[F][G]]] :)
  • +1,太棒了!非常感谢您的帮助@zx81。特别是对于 B 解决方案,我以前什至没有考虑过!我正在阅读您的答案,得分为 88,非常令人印象深刻!
  • @user3732025 感谢您提出的好问题,希望再次见到您! :)
【解决方案2】:

您可以使用此递归正则表达式,并打印最后一个匹配项:

s1 = 'AAA [BBB [CCC]]'
s2 = 'AAA [DDD] [EEE]'
s3 = 'AAA [BBB [CCC]] [EEE]'

import regex

for e in (s1, s2, s3):
    matches=regex.findall(r'[^\[\]\s]+ | \[ (?: (?R) | [^\[\]]+ )+\]', e, regex.VERBOSE)
    print(e, '=>', matches, '=>', matches[-1])

打印:

AAA [BBB [CCC]] => ['AAA', '[BBB [CCC]]'] => [BBB [CCC]]
AAA [DDD] [EEE] => ['AAA', '[DDD]', '[EEE]'] => [EEE]
AAA [BBB [CCC]] [EEE] => ['AAA', '[BBB [CCC]]', '[EEE]'] => [EEE]

【讨论】:

  • 非常感谢。其实这和预期的结果有点不同,@zx81 已经提供了很好的解决方案。
【解决方案3】:

离开你的给定数据并且你声明你想要最后一个组,我会为你提供这个递归正则表达式。

import regex

s1 = 'AAA [BBB [CCC]]'
s2 = 'AAA [DDD] [EEE]'
s3 = 'AAA [BBB [CCC]] [EEE]'

for s in [s1, s2, s3]:
    result = regex.findall(r'\[(?:[^[\]]|(?R))*\]', s)
    print result[-1]

输出

[BBB [CCC]]
[EEE]
[EEE]

【讨论】:

  • 非常感谢。但请参阅我的编辑以获得预期的结果。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多