我正在嘗試從可能包含或不包含數千或數百萬分隔符和小數的文本中提取“有效”數字。問題是有時分隔符是“,”,而在其他情況下是“。”,同樣適用于小數。我應該檢查是否有“,”或“。”的后驗出現。為了自動檢測字符是小數還是千位分隔符,除了條件\d{3}。
我發現的另一個問題是文本中存在格式為“dd.mm.yyyy”或“mm.dd.yy”的日期不必匹配。
目標是將“有效”數字轉換為float,我需要確保不是日期,然后洗掉百萬/千分隔符,最后將“,”替換為“。” 當小數點分隔符為“,”時。
我已經閱讀了其他很棒的答案,例如正則運算式來匹配文本中帶或不帶逗號和小數的數字,或在此處輸入鏈接描述以解決更具體的問題。我會對一些健壯的東西感到滿意(不需要在一個正則運算式命令中得到它)。
這是我迄今為止嘗試過的,但問題遠遠超出了我的正則運算式技能:
p = '\d (?:[,.]\d{3})*(?:[.,]\d*)'
for s in ['blabla 1,25 10.587.256,25 euros', '6.010,12', '6.010', '6,010', '6,010.12', '6010,124', '05.12.2018', '12.05.18']:
print(s, re.findall(p, s, re.IGNORECASE))
uj5u.com熱心網友回復:
您可以使用
import re
p = r'\b\d{1,2}\.\d{1,2}\.\d{2}(?:\d{2})?\b|\b(?<!\d[.,])(\d{1,3}(?=([.,])?)(?:\2\d{3})*|\d )(?:(?(2)(?!\2))[.,](\d ))?\b(?![,.]\d)'
def postprocess(x):
if x.group(3):
return f"{x.group(1).replace(',','').replace('.','')}.{x.group(3)}"
elif x.group(2):
return f"{x.group(1).replace(',','').replace('.','')}"
else:
return None
texts = ['blabla 1,25 10.587.256,25 euros', '6.010,12', '6.010', '6,010', '6,010.12', '6010,124', '05.12.2018', '12.05.18']
for s in texts:
print(s, '=>', list(filter(None, [postprocess(x) for x in re.finditer(p, s)])) )
輸出:
blabla 1,25 10.587.256,25 euros => ['1.25', '10587256.25']
6.010,12 => ['6010.12']
6.010 => ['6010']
6,010 => ['6010']
6,010.12 => ['6010.12']
6010,124 => ['6010.124']
05.12.2018 => []
12.05.18 => []
正則運算式是
\b\d{1,2}\.\d{1,2}\.\d{2}(?:\d{2})?\b|\b(?<!\d[.,])(\d{1,3}(?=([.,])?)(?:\2\d{3})*|\d )(?:(?(2)(?!\2))[.,](\d ))?\b(?![,.]\d)
詳情:
\b\d{1,2}\.\d{1,2}\.\d{2}(?:\d{2})?\b|- 匹配整個單詞、1-2 位、.、1-2 位、.、2 或 4 位(此匹配將被跳過)\b- 單詞邊界(?<!\d[.,])- 如果左邊有一個數字和一個.或,則匹配失敗后的否定回溯,(\d{1,3}(?=([.,])?)(?:\2\d{3})*|\d )- 第 1 組:\d{1,3}- 一位、兩位或三位數字(?=([.,])?)- 必須有一個可選的第 2 組捕獲 a.或,立即在右側(?:\2\d{3})*- 零個或多個第 2 組值序列,然后是任意三位數字|- 要么\d- 一位或多位數字
(?:(?(2)(?!\2))[.,](\d ))?- 一個可選的序列(?(2)(?!\2))- 如果組 2 匹配,下一個字符不能是組 2 值[.,]- 逗號或點(\d )- 第 3 組:一位或多位數字
\b- 單詞邊界(?![,.]\d)- 如果右邊有一個,或和一個數字,則匹配失敗。.
如果沒有匹配的捕獲組,或者整數部分中沒有逗號或點的數字,則該postprocess方法回傳None 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/429782.html
標籤:python-3.x 正则表达式
