[英]Python regex expression to remove hyphens between lowercase characters
我只需要删除小写字母之间的连字符。 这是我目前的表达方式:
re.sub('\[a-z]-\[a-z]', "", 'hyphen-ated Asia-Pacific 11-12')
我希望它返回:
'hyphenated Asia-Pacific 11-12'
两种方法,包括一些时间:
import re, timeit
def a1():
s = re.sub(r'([a-z])-([a-z])', r'\1\2', "hyphen-ated Asia-Pacific 11-12")
def a2():
s = re.sub(r'(?<=[a-z])-(?=[a-z])', '', "hyphen-ated Asia-Pacific 11-12")
print(timeit.timeit(a1, number = 10**5))
print(timeit.timeit(a2, number = 10**5))
产量
0.9709542730015528
0.37731508900105837
因此,在这种情况下,环视可能会更快。
TL;博士:
>>> re.sub('([a-z])-(?=[a-z])', r'\1', 'oblig-a-tory hyphen-ated Asia-Pacific 11-12')
'obligatory hyphenated Asia-Pacific 11-12'
或者
>>> re.sub('(?<=[a-z])-(?=[a-z])', '', 'oblig-a-tory hyphen-ated Asia-Pacific 11-12')
'obligatory hyphenated Asia-Pacific 11-12'
上下文替换的主要复杂性(“查找所有被小写字母包围的连字符”)是尾随上下文(要匹配的模式之后的部分)不能包含在匹配中。 如果是,它将无法参加下一场领先的比赛。
一个例子可能会更清楚。
天真的解决方案是
>>> re.sub('([a-z])-([a-z])', r'\1\2', 'hyphen-ated Asia-Pacific 11-12')
'hyphenated Asia-Pacific 11-12'
这与问题中的调用不同,因为它匹配连字符周围的小写字母,捕获它们以便可以将它们重新插入结果中。 在这种情况下,与模式匹配的唯一 substring 是na
并且它被正确替换为na
。
但是假设我们有两个更靠近的连字符,如下所示:
>>> re.sub('([a-z])-([a-z])', r'\1\2', 'oblig-a-tory hyphen-ated Asia-Pacific 11-12')
'obliga-tory hyphenated Asia-Pacific 11-12'
a
是匹配ga
的一部分,搜索在a
之后的-
处继续。 所以它从来没有在at
看到过匹配的模式。
为了解决这个问题,我们可以使用前瞻断言:
>>> re.sub('([a-z])-(?=[a-z])', r'\1', 'oblig-a-tory hyphen-ated Asia-Pacific 11-12')
'obligatory hyphenated Asia-Pacific 11-12'
现在尾随上下文(连字符后面的小写字母)不是匹配的一部分,因此我们不需要在替换中重新插入它。 这意味着在将g-
与尾随a
匹配后,搜索将从a
开始,下一个匹配将是a-
与尾随t
。
Python 也可以做“lookbehinds”,其中一个模式只有在另一个模式之前才匹配。 使用lookbehind和lookahead,我们可以这样写:
>>> re.sub('(?<=[a-z])-(?=[a-z])', '', 'oblig-a-tory hyphen-ated Asia-Pacific 11-12')
'obligatory hyphenated Asia-Pacific 11-12'
这也产生了正确的答案。 现在我们只是匹配连字符,但坚持在它之前和之后是一个小写字母。 由于匹配只是连字符,因此替换字符串可以为空。
有时使用像这样的lookbehind可以加快匹配速度。 有时它会减慢它的速度。 如果速度对您很重要,那么使用特定模式进行基准测试总是值得的。 但首要任务是正确匹配。
re.sub(r'([a-z])-([a-z])', r'\1\2', "hyphen-ated Asia-Pacific 11-12")
捕获连字符前后的字母,并在剥离连字符时保留它们。 \1
和\2
表示第一个和第二个捕获的组,在这种情况下是字母。
您当前的代码匹配连字符周围的两个字母并删除整个匹配项。 替换时应保留字母。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.