簡體   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