非贪婪模式的Python正则表达式

3
我正在尝试学习一些正则表达式,使用的是Python。
我现在的任务是爬取报纸文章并查找人们死亡的情况。当我找到相关文章后,我会尝试获取一些其他信息的死亡计数。我正在努力想出一些模式,但有一个特别困难。看看这篇文章节选:
据部落消息和当地官员称,10月21日(星期天),美国无人机袭击也门一辆汽车,疑似击毙了三名基地组织武装分子。
我用来获取“三”的代码替换了整个文档,因此在应用任何模式之前,“三”就变成了“3”。与此示例相关的模式如下所示:
re.compile(r"(\d+)\s(:?men|women|children|people)?.*?(:?were|have been)? killed")

这个模式的想法是以数字开头,后面跟着可选的名词,例如列出的其中一个名词,然后在找到“dead”或“died”之前有最少的杂乱内容。我希望留出空间,使得这个模式可以匹配:

3 people have been killed since Sunday

并且仍然可以在示例中捕获该实例:
3 men thought to be al qaeda militants were killed

问题在于我使用的模式从文章的第一部分收集日期,并返回计数21。到目前为止,无论我如何摆弄都不能使范围限制在单词“男人”旁边的数字上,其后是动词短语,然后是相关的“被杀害”。如果能有所帮助,我会非常感激。对于正则表达式方面我并不精通。
3个回答

3
不要将men|women|children设为可选项,即去掉右括号后面的问号。正则引擎将在尽可能早的位置进行匹配,无论重复操作符是贪婪还是懒惰。
另外,或者也可以将“任何内容”模式仅匹配非数字字符,即用\D*?替换.*?

\D 工作正常,从语法上讲似乎是最合理、最可扩展的。 - hyleaus

2
这是因为您使用了量词“?”来匹配数字后的“(?:men|women|children|people)”中的0或1个。因此,“21”将匹配成功,因为它有0个。请尝试删除量词,以确切地匹配其中一个:-
re.compile(r"(\d+)\s(?:men|women|children|people).*?(?:were|have been)? killed")

更新:- 如果要使用? quantifier并仍然获得所需的结果,则需要使用Look-Ahead正则表达式,以确保您的digit后面没有包含hiephen(-)的字符串,就像您的示例中一样。
re.compile(r"(\d+)(?!.*?-.*?)\s(?:men|women|children|people)?.*?(?:were|have been)? killed")

指定一个明确的重复次数为一完全是多余的。 - tripleee
我不想要 {1},因为有可能文章会这么写:‘星期天爆炸中有3人死亡...’ - hyleaus
@tripleee。是的,那是真的。我已经引用了那个东西。但 {1} 给了他使用另一个“量词”的方法。 - Rohit Jain
@hyleaus。然后您需要使用“Look-Behind”。检查它是否前面有一个“连字符(-)”,就像您的示例中一样。 - Rohit Jain
我尝试了你的版本,但解释器告诉我,向后查找需要一个固定宽度的模式。 - hyleaus
@hyleaus,抱歉,出现了问题。已编辑正则表达式,请尝试最新的版本。 - Rohit Jain

0

您使用了错误的语法(:?...)。您可能想要使用(?:...)


使用正则表达式模式
(\d+).*?\b(?:men|women|children|people|)\b.*?\b(?:were|have been|)\b.*?\bkilled\b

或者如果这些单词之间只允许空格,则

(\d+)\s+(?:men|women|children|people|)\s+(?:were|have been|)\s+killed\b

你说得对。那是错误的语法,但因为我只关心 .group(1),所以它并没有影响结果。不过还是谢谢你的关注。 - hyleaus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接