正则表达式搜索多个后缀

4

我有一个包含大量目标单词的列表,需要搜索。

words = ['Word1', 'Word2', 'Word3']

我听说这样的正则表达式:

suffix = re.compile('(?:{words}) (\\w+)'.format(words='|'.join(words)))

这种方法非常高效,因为当遇到不匹配表达式的字符时,它会立即停止正则表达式的评估。

然而,反过来做就不是很高效了:

prefix = re.compile('(\\w+) (?:{words})'.format(words='|'.join(words)))

有没有一种优雅的方法来指示Python的正则表达式进行反向搜索?

编辑

我被要求添加使用示例:

# prefix search
title = re.compile('(?:Mr.|Mrs.|Ms.|Dr. |Lt.) (\\w+)')
# suffix search
company = re.compile('(\\w+) (?:Inc.| LLP.|ltd.|GMBH)')
# invoking the regex
all_people_names  = title.findall(document)
all_company_names = company.findall(document)

编辑2

很多人对时间差异的重要性持怀疑态度。

我已经实现了两种方法:endswith()endswith_rev(),这些都是kabanus建议的字符串反转和结果。

以下是结果:

Timing

正如你所看到的,即使只有少量后缀,它也会产生巨大的影响。


你能否在问题中添加更多细节,例如你尝试匹配的示例等。 - Julian Camilleri
此外,上述方法通常并不会非常低效。性能提升主要是因为正则表达式可以使用动态规划同时检查多个子字符串。 - Willem Van Onsem
@UriGoren:不,"$"是字符串结尾的锚点。 - Willem Van Onsem
@WillemVanOnsem,$锚点并没有什么用,比如对于文本'google inc is nice, but apple inc is nicer',我想要re.findall返回['google', 'apple']。如果我使用$指令,则会强制表达式出现在搜索字符串的末尾,从而返回[] - Uri Goren
哦,哇,令人印象深刻,好的优化问题,我猜正则表达式在底层确实不是那么聪明。 - kabanus
显示剩余2条评论
3个回答

2

嗯,按照你的方法,你必须测试所有可能的前缀直到后缀。如果字符串足够长,则有一种方法可以打败它,那就是反转所有内容,这样你就回到了第一个示例:

prefix = re.compile('(?:{words}) (\\w+)'.format(words='|'.join([word[::-1] for word in words])))
re.match(prefix,mystring[::-1])

所以,您正在从末尾搜索,并获取相同的模式-不过请记住反转匹配。显然,这是一个主要的优化提升器,请参考OP获得一些时间。


谢谢,我已经更新了我的问题并附上了时间,这非常有趣。 - Uri Goren

1
在某些情况下,使用正则表达式是可以的,或者在其他情况下是必需的,例如当您配置一个允许您匹配模式且输入类型为RegEx模式的系统时,但对于这个简单的用例,使用RegEx只会浪费CPU周期。
这种用例很简单,因为您知道要匹配子字符串的位置 - 它们始终位于输入的末尾,所以每个“后缀”要么与给定的“inputString”匹配,要么不匹配:
inputString[ len(inputString) - len(suffix) : ] == suffix

当然,您已经有了Python方法endswith(suffix),因此您可以使用以下方式进行测试:

inputString.endswith( suffix )
< p > suffix 参数可以是一个 tuple,因此您可以执行以下操作:

suffixes = ( "Inc.", "inc.", "Gmbh", "ltd.", "LTD", "LLP" )
inputString.endswith( suffixes )

或者进行不区分大小写的搜索:

suffixes = ( "inc.", "gmbh", "ltd.", "llp" )
inputString.lower().endswith( suffixes )

无论如何,如果性能真的很重要,那么Python可能不是最好的语言。


我正在寻找“查找所有”功能,而不是“匹配”功能,因此“endswith”并没有太大帮助。 - Uri Goren
@UriGoren 如果匹配成功,您将其添加到结果中,是这样吗?在您的示例中,“document”具有哪些值?它只是一个简单的短语,例如名称或公司名称,还是需要解析的复杂文档?我非常想看看RegEx和其他解决方案之间的性能差异。您是否可以在某个地方发布您的测试用例? - isapir

0

try .*\.(?:jpg|gif|png)

将匹配

1.jpg
b.png
c.gif

https://regex101.com/上进行测试

Non-capturing group (?:jpg|gif|png)
1st Alternative jpg
jpg matches the characters jpg literally (case sensitive)
2nd Alternative gif
gif matches the characters gif literally (case sensitive)
3rd Alternative png
png matches the characters png literally (case sensitive)
Global pattern flags 
g modifier: global. All matches (don't return after first match)

请注意,此问题涉及性能而非正确性。 在单个正则表达式中搜索多个后缀对于大型文本非常低效,因为算法以线性方式工作。 在处理后缀时,翻转字符串和模式是正确的方法。 - Uri Goren

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