什么正则表达式可以捕获括号/圆括号内的多个实例?

5
我该如何使用正则表达式来捕获括号内的空格字符运行,例如在字符串中:"abc and 123 {foo-bar bar baz } bit {yummi tummie} byte."。我应该在{}内找到四个匹配项,但不包括其他内容。假设使用Python语言,并且字符串内容未知。编辑:还假设没有嵌套的括号。

1
是否存在嵌套的大括号? - gil
1
可能会出现这样的情况:abc { abc } a { a }abc { a { b } }吗? - Norman
@gill 不是的。没有嵌套的花括号。 - Eyeofpie
在您编辑的示例中,匹配四个空格 - 在第一个括号中 - 是否有可能顺序颠倒?("yummi tummie" 在 "foo-bar bar baz "之前)? - JustMe
也许你的意思不是“每个空格字符”,而是“每个连续的空格字符”?在你的例子中有7个这样的空格,但只有4个连续的空格。 - gil
显示剩余3条评论
3个回答

7

1
好的,假设没有悬挂的 } - gil
2
这只是一个在ideone.com上的快速演示,用来完善你美丽的正则表达式。 - Jan
这将匹配 {} 对外的空格。 - Norman
1
@bobble 啊,抱歉,我刚才和gill说了同样的事情,关于“悬挂的}”。 - Norman

3
>>> s = 'abc   and 123 {foo-bar     bar baz } bit {yummi tummie} byte.'
>>> inside_braces = re.findall(r'\{.*?\}', s)
>>> spaces_inside_braces = [re.findall(r' +', match) for match in inside_braces]
>>> [match for mlist in spaces_inside_braces for match in mlist]  # flatten list
['     ', ' ', ' ', ' ']
  1. 我们需要在r'\{.*?\}'中使用?来非贪婪地匹配花括号。
  2. 虽然可能可以在一行内完成所有操作,但那会太长了。
  3. 我想不到只用一个正则表达式就能完成所有操作的方法。这似乎是不可能的,因为我们有递归(甚至是左递归):即,在匹配模式之前应该匹配{和任意数量的.w。如果我没记错的话,即使回溯不需要固定长度的模式,正则表达式也无法处理这种情况。

我喜欢这个想法,但是OP说要在括号内的任何单词之前和之后。 - JustMe
@JustMe 你说得对。不知道我怎么看漏了。我会修复的。 - gil
@JustMe 哦不... OP 没有说“在任何单词之后和之前”。但我以另一种方式误读了问题...已经修正了。 - gil
嗯,你说得对;)但是似乎OP没有很明确——在括号中说“每个空格”,但是只有四个空格——而在单词之间有五个空格,在单词后面还有两个空格,总共是七个。 - JustMe
@JustMe 我认为 OP 的意思是“每个空格字符的连续出现”,因为期望的匹配次数是 4。 - gil

0

如果您可以使用替代正则表达式模块,那么您可以使用单个正则表达式完成它。但是,这很复杂且难以阅读。但它可以正确处理悬挂的大括号。

regex模块支持访问捕获组的所有先前匹配项,这对于以下内容至关重要:

>>> import regex
>>> # The regex behavior version seems to make no difference in this case, so both '(?V0)...' and '(?V1)...' will work.
>>> pattern = r'(?V0)[{]   (?P<u>\s+)?  (?: (?: [^\s}]+ (?P<u>\s+) )*  [^\s}]+ (?P<u>\s+)? )?   [}]'
>>> string = 'abc   and 123 {foo-bar     bar baz } bit {yummi tummie} byte.'
>>> [s for m in regex.finditer(pattern, string, regex.VERBOSE) for s in m.captures('u')]
['     ', ' ', ' ', ' ']

简单来说,这个正则表达式可以匹配形式为'{' blanks? ((nonblanks blanks)* nonblanks blanks?)? '}'的内容,并将所有空格部分分配到同一个名为u ((?P<u>...))的捕获组中。

它还可以处理包含未匹配的{}字符的字符串:

>>> # Even works with dangling braces:
>>> badstring = '}oo} { ab  a   b}}  xy {xy  x y}cd {{   cd  } e{e }f{ f}  { }{} }{'
>>> # Fully flattened result:
>>> [s for m in regex.finditer(pattern, badstring, regex.VERBOSE) for s in m.captures('u')]
[' ', '  ', '   ', '  ', ' ', '   ', '  ', ' ', ' ', ' ']
>>> # Less flattened (e.g. for verification):
>>> [v for m in regex.finditer(pattern, badstring, regex.VERBOSE) for v in m.capturesdict().values()]
[[' ', '  ', '   '], ['  ', ' '], ['   ', '  '], [' '], [' '], [' '], []]

已在 Python 3.5.1 x64 和 regex 2016.3.2 上进行测试。


不幸的是,这会抛出一个错误:后顾需要固定宽度模式 - Eyeofpie
我改进了我的答案,以使其实际起作用。虽然不够优雅和易读,但至少现在是正确的 :-) - Norman

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