2017-09-02 92 views
2

我的文檔正則表達式來獲得測量

5.3 x 2.5 cm 
11 x 11 mm 
7 mm 
13 x 12 x 14 mm 
13x12cm 

我需要使用Python使用正則表達式來提取5.3×2.5釐米的這些測量。

到目前爲止,我的代碼如下,但它不能正常工作

x = "\.\d{1,2}|\d{1,4}\.?\d{0,2}|\d{5}\.?\d?|\d{6}\.?" 
by = "()?(by|x)()?" 
cm = "(mm|cm|millimeter|centimeter|millimeters|centimeters)" 
x_cm = "((" + x + " *(to|\-) *" + cm + ")" + "|(" + x + cm + "))" 
xy_cm = "((" + x + cm + by + x + cm + ")" +"|(" + x + by + x + cm + ")" +"|(" + x + by + x + "))" 
xyz_cm = "((" + x + cm + by + x + cm + by + x + cm + ")" + "|(" + x + by + x + by + x + cm + ")" + "|(" + x + by + x + by + x + "))" 
m = "((" + xyz_cm + ")" + "|(" + xy_cm + ")" + "|(" + x_cm + "))" 
a = re.compile(m) 
print a.findall(text) 

輸出它給:

[('13', '13', '13', '13', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('12', '12', '12', '12', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('4', '4', '4', '4', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), ('25', '25', '25', '25', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''), 
+2

定義「不能正常工作」:它做什麼與做什麼應該做什麼?例子將是最受歡迎的。 –

+0

請顯示並解釋您所獲得的輸出與您想要的輸出之間的差異。 – Yunnosch

+1

你必須做的一件事是擺脫捕獲組。但是,您應該在連接後檢查[最終模式](https://regex101.com/r/LcTavz/1),它僅[返回數字](https://ideone.com/TOX9eK)。 –

回答

2

與當前的正則表達式唯一的問題是兩個:

  • 您需要自.findall擺脫捕獲組將提取抓獲,而不是整個匹配值(然而,這不是關鍵的所有子,你不妨使用re.finditer並得到match.group(0)
  • 主要問題是,你沒有組x模式,數字格式替代破壞了最終模式的結構。

速戰速決看起來像

x = "(?:\.\d{1,2}|\d{1,4}\.?\d{0,2}|\d{5}\.?\d?|\d{6}\.?)" 
by = "(?:)?(?:by|x)(?:)?" 
cm = "(?:mm|cm|millimeter|centimeter|millimeters|centimeters)" 
x_cm = "(?:" + x + " *(?:to|\-) *" + cm + "|" + x + cm + ")" 
xy_cm = "(?:" + x + cm + by + x + cm +"|" + x + by + x + cm +"|" + x + cm + by + x +"|" + x + by + x + ")" 
xyz_cm = "(?:" + x + cm + by + x + cm + by + x + cm + "|" + x + by + x + by + x + cm + "|" + x + by + x + by + x + ")" 
m = "{}|{}|{}".format(xyz_cm, xy_cm, x_cm) 

Python demo印刷

['5.3 x 2.5', '11 x 11', '13 x 12 x 14', '13x12cm'] 

爲了進一步增強它,想到的xbycm所有的可能性,並可能使用str.format代替串聯。

3

用正則表達式,你應該總是慢慢建立起自己的表現來得到你想要的。例如。

s = "5.3 x 2.5 cm" 

你想在這裏找到數字?

re.findall("\d+", s) 

給你所有的整數:

["5", "3", "2", "5"] 

好了,如果你的號碼可以浮點但不必須。然後你用一個沒有捕獲的匹配組擴大你的表情,這個匹配組有一個點,也許跟隨一些數字。

re.findall("\d+(?:\.\d*)?", s) 

這給你

["5.3", "2.5"] 

那麼你可以採取乘法與周圍的空間中任意數量:

re.findall("(\d+(?:\.\d*)?)\s*x\s*(\d+(?:\.\d*)?)", s) 

把號碼匹配組現在給你一個元組。

[("5.3", "2.5")] 

然後,您可以去與單位:

re.findall("(\d+(?:\.\d*)?)\s*x\s*(\d+(?:\.\d*)?)\s*(cm|mm)", s) 

給你你想要的元組:

[("5.3", "2.5", "cm")] 

等。

如果你這樣構建你的正則表達式,你有機會看到從一個變化到下一個變化的休息時間。調試上面發佈的一個巨大的正則表達式是一項不值得的任務。

我不會將我的單元正則表達式命名爲cm,這對將來維護您的代碼的任何人來說都相當混亂。除此之外,您需要對您希望允許的數字格式有一些明確的要求。也許有人會輸入科學記數法等你的正則表達式會變得非常複雜。

+0

感謝它解決了我的問題!還要特別感謝您的所有詳細解釋! – user1979556

+0

當只有一個尺寸(7毫米)時,它沒有找到唯一的東西,但我會找出它。 – user1979556

+0

@ user1979556我認爲這可以作爲練習留給讀者;-)。 – CodeMonkey