python中的正则表达式 - 带有可选短语的麻烦

时间:2014-09-09 12:22:28

标签: python regex

我需要一个小脚本来过滤给定文本中的文献参考。引用可以采用两种格式:

bla bla bla(Snowden,2014a)bla bla bla(Bush and Blair,2005)bla bla bla。

通过两次搜索找到这些参考资料:

matches1 = re.findall('\([A-Z]\w*,\s?\d\d\d\d[a-z]?\)', line)
matches2 = re.findall('\([A-Z]\w* and [A-Z]\w*,\s?\d\d\d\d[a-z]?\)', line)

这些搜索正确地找到(Snowden,2014a)。 (布什和布莱尔,2005年)。但现在我想在一次搜索中找到这两种引用,但它失败了:

matches1 = re.findall('\([A-Z]\w*( and [A-Z]\w*)?,\s?\d\d\d\d[a-z]?\)', line)

此搜索返回''而不是(斯诺登,2014a)和'和布莱尔'而不是(Bush和Blair,2005)。我不清楚为什么会发生这种情况或者我做错了什么,所以任何帮助都值得赞赏:)

谢谢!

2 个答案:

答案 0 :(得分:2)

只需将捕获组转为非捕获组,然后将\d\d\d\d缩减为\d{4}。因为re.findall给予群组首选。如果存在任何组,则它将仅打印组内存在的字符。它忘记了匹配的字符串。

\([A-Z]\w*(?: and [A-Z]\w*)?,\s?\d{4}[a-z]?\)

示例代码:

>>> import re
>>> s = """foo bar (Snowden, 2014a)
... (Bush and Blair, 2005) foo bar"""
>>> m = re.findall(r'\([A-Z]\w*(?: and [A-Z]\w*)?,\s?\d{4}[a-z]?\)', s, re.M)
>>> for i in m:
...     print i
... 
(Snowden, 2014a)
(Bush and Blair, 2005)

答案 1 :(得分:0)

通过添加?:

使您的可选群组无法捕获
In [8]: re.findall('\([A-Z]\w*(?: and [A-Z]\w*)?,\s?\d\d\d\d[a-z]?\)', line)
Out[8]: ['(Snowden, 2014a)', '(Bush and Blair, 2005)']