![](/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.