如何用Python正则表达式匹配‘plays/played’后首个‘for’的相关短语?
解决Python正则匹配"plays/played for"及中间插入词的问题
嘿,我来帮你搞定这个正则难题!你想要匹配"plays for"、"played for",还有中间插了其他单词的情况(比如"played guitar for"),而且只抓"plays"或"played"之后第一个出现的"for",对吧?
先说说你原来正则的问题:
- 你写的
[s|e]是错误的,字符集里的竖线|会被当成普通字符,应该写成[es]才对; - 另外
.*是贪婪匹配,它会一直匹配到文本里最后一个"for",这显然不是你想要的结果。
正确的正则表达式
我给你调整后的正则,能完美满足需求:
r'\bplay(?:s|ed)\b.*?\bfor\b'
逐部分解释
\b:单词边界,确保我们匹配的是完整的"plays"或"played",不会误匹配比如"playing"里的play片段;play(?:s|ed):匹配"plays"或者"played",这里用(?:...)非捕获组,只是用来分组选择,不会额外存储匹配结果,比普通捕获组更高效;.*?:非贪婪模式的任意字符匹配,它会在遇到**第一个"for"**时就停止匹配,刚好符合你要的"只匹配第一个for实例"的要求;\bfor\b:同样用单词边界,确保匹配的是完整的"for"单词,不会误匹配比如"forever"里的for前缀。
完整代码示例
把正则放到你的函数里,测试一下效果:
import re def play_finder(doc): # 编译正则,启用非贪婪匹配 playre = re.compile(r'\bplay(?:s|ed)\b.*?\bfor\b') # 查找所有符合条件的短语 matches = playre.findall(doc) return matches # 测试用例 test_doc = """ Maria plays for the school basketball team. John played drums for his band last night, then played keys for the encore. We should ignore "play for" since it's not plays/played. """ # 运行并打印结果 print(play_finder(test_doc)) # 输出:['plays for', 'played drums for', 'played keys for']
进阶:拆分捕获内容
如果你想单独获取"plays/played"部分和中间的内容,可以改成带捕获组的正则:
r'\b(play(?:s|ed))\b(.*?)\bfor\b'
这样findall会返回元组列表,每个元组里第一个元素是动词部分,第二个是中间的内容,比如对于"played drums for",会返回('played', ' drums ')。
内容的提问来源于stack exchange,提问作者AdeDoyle
相关产品推荐
相关产品推荐

