簡體   English   中英

Python,正則表達式匹配數字,x,xxx,xxx但不是xx,xx,x,

[英]Python, regular expression matching digits, x,xxx,xxx but not xx,xx,x,

第一次發帖,我已經潛伏了一段時間,對這里有用的社區感到非常興奮。

因此,與Al Sweigart合作“自動化無聊的東西”

做一個需要我構建一個以標准數字格式查找數字的正則表達式的練習。 三位數,逗號,三位數,逗號等...

所以希望能匹配1,234和23,322和1,234,567和12但不是1,23,1或者1111,或者其他任何愚蠢的東西。

我有以下內容。

import re

testStr = '1,234,343'
matches = []
numComma = re.compile(r'^(\d{1,3})*(,\d{3})*$')

for group in numComma.findall(str(testStr)):
    Num = group
    print(str(Num) + '-')           #Printing here to test each loop
    matches.append(str(Num[0]))

#if len(matches) > 0:
#    print(''.join(matches))

哪個輸出....

('1',',343') -

我不確定為什么中間的“,234”被跳過了。 正如我所說,正則表達式有問題。 似乎無法繞過這一個。

任何幫助或解釋將不勝感激。

跟隨編輯。 因此,在遵循了我可以吸收的所有建議之后,我完全可以為幾個輸入工作。

import re

testStr = '1,234,343'
numComma = re.compile(r'^(?:\d{1,3})(?:,\d{3})*$')

Num = numComma.findall(testStr)
print(Num)

給我....

[ '1234343']

大! 但! 當我將字符串輸入更改為類似的內容時怎么樣?

'1,234,343和12,345'

相同的代碼返回....

[]

Grrr ......哈哈,這很有趣,我必須承認。

因此,練習的目的是能夠最終掃描一段文本並以此格式挑選出所有數字。 任何見解? 我以為這會添加一個額外的元組,而不是返回一個空元組...

跟隨編輯:

所以,一天之后(忙於3個女兒和親愛的名單),我終於能夠坐下來檢查我收到的所有幫助。 這就是我想出來的,它看起來完美無瑕。 包括我個人理解的評論。 再次感謝Blckknght,Saleem,mhawke和BHustus。

我的最終代碼:

import re

testStr = '12,454 So hopefully will match 1,234 and 23,322 and 1,234,567 and 12 but not 1,23,1 or ,,1111, or anything else silly.'

numComma = re.compile(r'''
    (?:(?<=^)|(?<=\s))  # Looks behind the Match for start of line and whitespace
    ((?:\d{1,3})        # Matches on groups of 1-3 numbers.
    (?:,\d{3})*)        # Matches on groups of 3 numbers preceded by a comma
    (?=\s|$)''', re.VERBOSE)    # Looks ahead of match for end of line and whitespace

Num = numComma.findall(testStr)
print(Num)

哪個回報:

['12,454','1,234','23,322','1,234,567','12']

再次感謝! 我在這里有過如此積極的首發​​經歷,太棒了。 =)

問題是由於您在模式中使用重復捕獲組(,\\d{3})* Python的正則表達式引擎將匹配數字的千位和一組,但只捕獲最后一次重復。

我懷疑你想要使用非捕獲組。 添加?:到每組括號的開頭(我還建議,在一般原則上,使用原始字符串,盡管在當前模式中沒有轉義問題):

numComma = re.compile(r'^(?:\d{1,3})(?:,\d{3})*$')

由於沒有捕獲任何組, re.findall將返回整個匹配的文本,我認為這是你想要的。 您還可以使用re.findre.search並在返回的match對象上調用group()方法以獲取整個匹配的文本。

問題是:

正則表達式匹配將返回每個組的元組項。 但是 ,區分群組捕捉是很重要的。 由於您只有兩個以括號分隔的組,因此匹配將始終為兩個元組:第一組和第二組。 但第二組比賽兩次。

1 :第一組,被捕獲
,234 :第二組,被捕獲
,343也是第二組,這意味着它被覆蓋 ,234

不幸的是 ,似乎vanilla Python沒有辦法以類似於.NET的正則表達式實現的方式訪問除最后一個組之外的任何組的捕獲。 但是 ,如果您只想獲得具體的數字,最好的辦法是使用re.search(number) 如果它返回非None值,則輸入字符串是有效數字。 否則,事實並非如此。

另外:對你的正則表達式進行測試 請注意,正如Paul Hankin所說,測試用例6和7雖然不應該匹配,但是由於第一個捕獲組之后的第一個*,這將使初始組匹配任意次。 否則,你的正則表達式是正確的。 固定版本。

對編輯的反應:
現在你的正則表達式在'和'上返回一個空集的原因是你的正則表達式中的^和$錨。 在正則表達式開頭的^錨點說'這一點需要在字符串的開頭'。 $是它的對手,說'這需要在字符串的末尾'。 如果您希望整個字符串從頭到尾與模式匹配,那么這很好,但是如果您想要選擇多個數字,則應該取消它們。

然而!
如果將正則表達式保留為當前形式的sans anchors,它現在將1,23,45的各個元素作為單獨的數字匹配。 因此,我們需要添加一個零寬度的正向前瞻斷言,並說“確保在此數字后面是空格或行的末尾”。 你可以在這里看到變化。 尾端(?=\\s|$) ,是我們的前瞻斷言:它不捕獲任何東西,但只是確保標准或滿足,在這種情況下是空格( \\s )或( | )一行的結尾( $ )。

但是:在類似的情況下,之前的正則表達式將在“1234,567”中匹配2向前,給我們數字“234,567”,這將是不好的。 因此,我們使用落后於年底類似於我們預測先行斷言一看: (?<!^|\\s)只匹配如果在字符串的開頭或有空格的數字前。 這個版本可以在這里找到,並且應該完全滿足任何非十進制數相關的需求。

嘗試:

import re
p = re.compile(ur'(?:(?<=^)|(?<=\s))((?:\d{1,3})(?:,\d{3})*)(?=\s|$)', re.DOTALL)

test_str = """1,234 and 23,322 and 1,234,567 1,234,567,891 200 and 12 but
not 1,23,1 or ,,1111, or anything else silly"""

for m in re.findall(p, test_str):
    print m

它的輸出將是

  • 1,234
  • 23,322
  • 1,234,567
  • 1,234,567,891
  • 200
  • 12

你可以在這里看到演示

此正則表達式將匹配任何有效數字,並且永遠不會匹配無效數字:

(?<=^|\\s)(?:(?:0|[1-9][0-9]{0,2}(?:,[0-9]{3})*))(?=\\s|$)

https://regex101.com/r/dA4yB1/1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM