我正在尝试编写一个匹配形式为##-##
的字符串的正则表达式(其中#对应于任何数字),但需要注意的是第二对数字不能为“00”。该表达式应该与re.search一起使用,并且应该捕获匹配模式的第一次出现。
这是我得到的(有效):
the_regex = re.compile("(\d\d-(?:0[123456789]|[123456789]\d))")
我不喜欢分支或长字符组。任何人都可以建议一个更好的(更清晰,或可选,更有效)正则表达式吗?
(是的,这是微观优化,我已经听从了Knuth的正确警告。)
答案 0 :(得分:4)
使用字符范围可以轻松解决长字符组:
r"(\d\d-(?:0[1-9]|[1-9]\d))"
但你无法避开这里的分支。
答案 1 :(得分:3)
the_regex = re.compile("(\d\d-(?:0[1-9]|[1-9]\d))")
l = re.findall(the_regex, '11-01 11-99 10-29 01-99 00-00 11-00')
print l
所示:
['11-01', '11-99', '10-29', '01-99']
如果你使用re.finditer,它会返回一个生成器,这对你来说可能更好:
it = re.finditer(the_regex, '11-01 11-99 10-29 01-99 00-00 11-00')
print type(it)
print list(i.group(0) for i in it)
显示了这一点:
<type 'callable-iterator'>
['11-01', '11-99', '10-29', '01-99']
答案 2 :(得分:1)
另一种可能性......我不确定这是否可行,但似乎......它使用了前瞻断言:
r2 = re.compile(r"(\d\d-(?!00)\d\d)")
l = re.findall(r2, 'On 02-14 I went looking for 12-00 and 14-245')
print l
['02-14', '14-24']
然而......它似乎没有更快(与上述解决方案相比)。事实上,最初的解决方案是最快的:
# Martijn/Aaron's solution
In [20]: %timeit l = re.findall(the_regex2, '11-01 11-99 10-29 01-99 00-00 11-00')
100000 loops, best of 3: 3.55 µs per loop
# Above version
In [21]: %timeit l = re.findall(r2, '11-01 11-99 10-29 01-99 00-00 11-00')
100000 loops, best of 3: 3.49 µs per loop
#Original post's version.
In [25]: the_regex = re.compile("(\d\d-(?:0[123456789]|[123456789]\d))")
In [26]: %timeit l = re.findall(the_regex, '11-01 11-99 10-29 01-99 00-00 11-00')
100000 loops, best of 3: 3.41 µs per loop