有没有办法将以下三个表达式合并为一个正则表达式?
name = re.sub(r'\s?\(\w+\)', '',name) # John Smith (ii) --> John Smith
name = re.sub(r'\s?(Jr.|Sr.)$','', name, flags=re.I) # John Jr. --> John
name = re.sub(r'".+"\s?', '', name) # Dwayne "The Rock" Johnson --> Dwayne Johnson
答案 0 :(得分:6)
答案 1 :(得分:1)
如果你想获得一个有效的(并且大部分时间都在工作)模式,简单地用管道分离你的模式是一个坏主意。你必须重新考虑你想对你的模式做什么,并从头开始重写它。
p = re.compile(r'["(js](?:(?<=\b[js])r\.|(?<=\()\w+\)|(?<=")[^"]*")\s*', re.I)
text = p.sub('', text).rstrip()
这是一个很好的机会,可以批评您之前所写的内容:
\s?
启动模式的速度很慢,因为必须使用和不使用此字符测试字符串中的每个位置。因此,最好在末尾捕获可选的空格并在之后修剪字符串。 (在所有情况下,即使您决定在开始时捕获可选空格,也需要修剪结果) "[^"]*"
(注意:这可以改进以处理引号内的转义引号) Jr.
和Sr.
的模式也是假的,以匹配您需要逃避它的文字.
。除了
这种模式太不精确了,因为它之前没有检查是否有其他单词字符。它将匹配例如以“USSR”结尾的句子。或任何包含“jr”的子串。或“sr。”。 (要完全严谨,你必须检查之前是否有空格或字符串的开头,但是大部分时间都应该有一个简单的单词边界) 现在如何建立你的交替:
顺序可能很重要,特别是如果子模式不是mutualy排他性的。例如,如果你有子模式a+b
和a+
,如果你写a+|a+b
,b
之前的所有a
将永远不会匹配,因为第一个分支以前成功了。但是对于你的例子,没有这种问题。
顺便说一句,如果你知道其中一个分支机构有更多机会成功,那就把它放在交替的第一个位置。
您知道搜索到的子字符串以以下字符之一开头:"
,(
,j
,s
。在这种情况下,为什么不用["(js]
开始模式,避免测试字符串中所有位置的模式的每个分支。
然后,由于已经消耗了第一个字符,因此您只需要使用lookbehind检查每个分支中哪些字符匹配。
通过这些小改进,您可以获得更快的模式。