繁体   English   中英

匹配特定数量的数字,该数字不得在数字之前或之后

[英]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=2m=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'的匹配实际上已消耗:

  1. e ,带有(?:\\D|^) –未捕获(但仍被消耗)
  2. 22 (\\d{2,3}) –已捕获
  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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM