我们说我有一个字符串:
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。
答案 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)