0

我正在使用 Python 2.x 中的正则表达式来捕获缩写的子集。以下文本中出现了几个这样的缩写:

# text                                    # desired capture
The certolizumab pegol (Cmzia, CZP)...      'CZP'
The drug 6-mercatopureine (6-mp) ...        '6-mp'
The merits of 5-Asasdfdsf (5-ASA) ...       '5-ASA'    

在第一个示例中,我有兴趣返回结果CZP并忽略Cmzia,.

这是我之前的正则表达式,它对于匹配和这样的情况是必要(6-mp)(5-ASA)

\((\S*[A-Z-0-9]\S*)\)  # captures '6-mp' and '5-ASA', respectively

这是我为处理上述情况所做的补充:

\S*\s+[A-Z-0-9]+  # I only want to capture the '[A-Z-0-9]+'

我尝试使用以下正则表达式(我尝试将感兴趣的部分加粗,以免与上下文混淆,但这似乎不起作用):

# in p1, I add the pattern to the list, separated by '|'
>>> p1 = re.compile(r'\((\S*[A-Z-0-9]\S*|\S*\s+[A-Z-0-9]+)\)')
>>> p1.findall('The certolizumab pegol (Cmzia, CZP)')
['Cmzia, CZP']

# in p2, I use a broad non-capturing group, enclosing the desired captured expressions in parentheses
>>> p2 = re.compile(r'\((?:(\S*[A-Z-0-9]\S*)|\S*\s+([A-Z-0-9]+))\)')
>>> p2.findall('The certolizumab pegol (Cmzia, CZP)')                           
[('', '', 'CZP')] 

# this is an addition to the original post
# demonstrates that the non-capturing expression doesn't prevent capture of the section \S*\s+
>>> p3 = re.compile(r'\((\S*[A-Z-0-9]\S*|(?:\S*\s+)[A-Z-0-9]+)\)')
>>> p3.findall('The certolizumab pegol (Cmzia, CZP)')                           
['Cmzia, CZP']

理想情况下,我想要输出CZP. p1返回太多,因为我想排除\S*\s+对应的Cmzia,. 关于p2,我知道我可以轻松地操纵输出以匹配我想要的输出,但我想知道是否有办法修改正则表达式来处理它。

谢谢,如果您需要更多详细信息/说明,请告诉我。

编辑:

我仍然希望正则表达式从正则表达式的第一个/原始部分捕获6-mpand 。5-ASA

编辑2:

这包括在上面,但把它放在一个位置并总结我的问题。

pattern = r'???'
p = re.compile(pattern)
p.findall('Stuff stuff (Cmzia, CZP) stuff stuff (5-ASA) (6-mp) stuff...')
['CZP','5-ASA','6-mp']
4

3 回答 3

1

这是我发现可以实现您的目标的最简单的正则表达式:

>>> p = "\((?:\S*,\s+)?(\S*)\)"
>>> s = "The cert pegol (Cmzia, CZP) some words (6-mp) and (5-ASA)"
>>> re.findall(p,s)
['CZP', '6-mp', '5-ASA']

更新

下一个更具限制性,但它给出了相同的结果:

>>> p = "\((?:\S*,\s+)?(\S*[A-Z-0-9]\S*)\)"
于 2012-10-24T12:17:21.197 回答
0

我不太明白你想要什么,但我在与“CZP”对应的部分周围添加了另一个匹配的括号,并使外部组不匹配,得到了这个:

>>> p3 = re.compile(r'\((?:\S*[A-Z-0-9]\S*|[A-Z-0-9]* [A-Z-0-9]*|(?:\S*\s+)([A-Z-0-9]+))\)')
>>> p3.findall('The certolizumab pegol (Cmzia, CZP)')
['CZP']
于 2012-10-24T03:04:07.213 回答
0

如果我没看错的话,括号内可以有一个或两个逗号分隔的值。如果是两个,您只想捕获第二个。试试这个:

p = re.compile(r'\((?:[^,)]+,\s*)?([A-Za-z0-9-]+)\)')

在开始的括号之后,(?:[^,)]+,\s*)?尝试匹配第一个值,它通过尾随逗号的存在来标识。您并不真正关心第一个值的外观,只要其中没有任何逗号即可。但是您不能仅仅[^,]+因为在只有一个值的情况下匹配太多而使用它。将括号添加到排除字符列表中,可以使匹配项包含在一组括号中。

于 2012-10-26T08:34:26.953 回答