正则表达式:贪婪与非贪婪匹配括号

8 投票
4 回答
2989 浏览
提问于 2025-04-16 18:02

我正在使用Python的正则表达式模块,叫做re

我需要匹配这两个短语中括号'('和')'之间的内容,但要“不是那么贪心”。就像这样:

show the (name) of the (person)

calc the sqrt of (+ (* (2 4) 3))

从短语1中,结果应该返回:

name
person

从短语2中,结果应该返回:

+ (* (2 4) 3)

问题是,为了匹配第一个短语,我用了'\(.*?\)'

但是在第二个短语中,这个表达式只匹配到了+ (* (2 4)

而如果我用'\(.*\)'来正确匹配第二个短语,那么在第一个短语中就会匹配到(name) of the (person)

那么,有什么正则表达式可以同时正确匹配这两个短语呢?

4 个回答

0

这段内容包含了所有需要的信息:

(?:\()(.*?\){2})|(?:\()(.*?)(?:\))

第一组 = + (* (2 4) 3)

  • 最后的右括号“)”可以用 .strip(')') 去掉

第二组 = name, person

0

你想做的事情看起来像是一个“换轨算法”,其实它有点像LISP语言,所以你可以看看这个PyLisp。其实不需要用正则表达式来解析这些表达式。

可以查看维基百科上的换轨算法文章,还有它在Python中的实现

8

Pyparsing 这个工具可以帮助你轻松地写一些简单的解析器,适合处理像这样的内容:

>>> text = """show the (name) of the (person)
...
... calc the sqrt of (+ (* (2 4) 3))"""
>>> import pyparsing
>>> for match in pyparsing.nestedExpr('(',')').searchString(text):
...   print match[0]
...
['name']
['person']
['+', ['*', ['2', '4'], '3']]

注意,这里嵌套的括号已经被去掉了,而嵌套的文本则以嵌套的结构返回。

如果你想要每个括号里的原始文本,可以使用 originalTextFor 修饰符:

>>> for match in pyparsing.originalTextFor(pyparsing.nestedExpr('(',')')).searchString(text):
...   print match[0]
...
(name)
(person)
(+ (* (2 4) 3))

撰写回答