正则表达式:如何找到两个正则表达式匹配之间的子字符串?

时间:2014-03-19 20:42:58

标签: python regex string python-3.x

我们说我有一个字符串:

data = 'MESSAGE: Hello world!END OF MESSAGE'

我希望得到'MESSAGE: '和下一个大写单词之间的字符串。消息中从来没有任何完全大写的单词。

我试图通过在re.search中使用此正则表达式来实现此目的:

re.search('MESSAGE: (.*)([A-Z]{2,})', data).group(1)

这里我希望输出'Hello world!' - 但它总是返回错误的结果。在正则表达式中很容易找到在两个其他字符串之间出现的子字符串,但是如何在正则表达式匹配的字符串之间找到子字符串。我试过把它变成原始字符串,但这似乎不起作用。

我希望自己表达得很好 - 我在Python方面有丰富的经验,但我对正则表达式不熟悉。如果可能的话,我想要一个解释以及如何使我的具体示例代码工作的示例。非常感谢任何有用的帖子。

BTW,我使用的是Python 3.3。

3 个答案:

答案 0 :(得分:3)

您的代码不起作用,但出于相反的原因:

re.search('MESSAGE: (.*)([A-Z]{2,})', data).group(1)

会匹配

'Hello world!END OF MESSA'

因为(.*)是"贪婪",即它匹配最多允许其余的(两个大写字符)匹配。你需要使用非贪婪的量词

re.search('MESSAGE: (.*?)([A-Z]{2,})', data).group(1)

正确匹配

'Hello world!'

答案 1 :(得分:2)

一个小问号:

re.search('MESSAGE: (.*?)([A-Z]{2,})', data).group(1)
Out[91]: 'Hello world!'

如果你让第一个捕获组变得懒惰,它就不会在感叹号之后消耗任何东西。

答案 2 :(得分:2)

你需要你的。*非贪婪(见第一个?)这意味着它在下一个项目可以匹配的点停止匹配,你需要第二个组不能捕获(见?:)。

import re 
data = 'MESSAGE: Hello world!END OF MESSAGE'    
regex = r'MESSAGE: (.*?)(?:[A-Z]{2,})'
re.search(regex, data).group(1)

返回:

'Hello world!'

或者,你可以使用它:

regex = r'MESSAGE: (.*?)[A-Z]{2,}'

要打破这一点(我将包含带有VERBOSE标志的搜索行:):

regex = r'''
         MESSAGE:\s    # first part, \s for the space (matches whitespace)
         (.*?)         # non-greedy, anything but a newline
         (?:[A-Z]{2,}) # a secondary group, but non-capturing,
                       #  good for alternatives separated by a pipe, |
         '''
re.search(regex, data, re.VERBOSE).group(1)
相关问题