![](/img/trans.png)
[英]Python Regex: Match a string not preceded by or followed by a word with digits in it
[英]Match a specific number of digits not preceded or followed by digits
我有一个字符串:
string = u'11a2ee22b333c44d5e66e777e8888'
我想找到所有k
个连续的数字块,其中n <= k <= m
。
仅使用正则表达式:使用(?:\\D|^)(\\d{2,3})(?:\\D|$)
例如说n=2
和m=3
re.findall(u'(?:\D|^)(\d{2,3})(?:\D|$)',u'11a2ee22b333c44d5e66e777e8888')
给出以下输出:
['11', '333', '66']
所需的输出:
['11', '22', '333', '44', '66', '777']
我知道还有其他解决方案,例如:
filter(lambda x: re.match('^\d{2,3}$', x), re.split(u'\D',r'11a2ee22b333c44d5e66e777e8888'))
哪个可以提供所需的输出,但是我想知道第一种方法有什么问题吗?
似乎re.findall
会按顺序进行,并在匹配时跳过前一部分,那么该怎么办?
注意:您在问题中显示的结果不是我得到的结果:
>>> import re
>>> re.findall(u'(?:\D|^)(\d{2,3})(?:\D|$)',u'11a2ee22b333c44d5e66e777e8888')
[u'11', u'22', u'44', u'66']
它仍然缺少您想要的一些比赛,但并非完全相同。
问题在于,即使像(?:\\D|^)
和(?:\\D|$)
这样的非捕获组都无法捕获它们匹配的对象,它们仍然会消耗它们。
这意味着产生'22'
的匹配实际上已消耗:
e
,带有(?:\\D|^)
–未捕获(但仍被消耗) 22
(\\d{2,3})
–已捕获 b
与(?:\\D|$)
–未捕获(但仍被消耗) …因此b
不再可用于333
之前的匹配。
您可以使用lookbehind和lookahead语法获得所需的结果:
>>> re.findall(u'(?<!\d)\d{2,3}(?!\d)',u'11a2ee22b333c44d5e66e777e8888')
[u'11', u'22', u'333', u'44', u'66', u'777']
在这里, (?<!\\d)
是一个负向后看,检查该匹配项是否不以数字开头,而(?!\\d)
是一个负向超前检查,以确保该匹配项后没有数字。 至关重要的是,这些构造不会消耗任何字符串。
Python re
文档的“ 正则表达式语法”部分介绍了各种先行和后向构造。
环绕正则表达式,\\ d {2,3}表示2或3位数字,(?= [az])表示数字后的字母。
In [136]: re.findall(r'(\d{2,3})(?=[a-z])',string)
Out[136]: ['11', '22', '333', '44', '66', '777']
您甚至可以使用以下函数将其概括:
import re
string = "11a2ee22b333c44d5e66e777e8888"
def numbers(n,m):
rx = re.compile(r'(?<!\d)(\d{' + '{},{}'.format(n,m) + '})(?!\d)')
return rx.findall(string)
print(numbers(2,3))
# ['11', '22', '333', '44', '66', '777']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.