2014-09-25 38 views
-2

我試圖將數據從一個在線的純文本的政府報告說,看起來像這樣來排序之間的正則表達式多搜索:Python的部分

Potato Prices as of 24-SEP-2014 
Idaho 
BrownSpuds 
    SomeSpuds 1.90-3.00 mostly 2.00-2.50 
    MoreSpuds 2.50-3.50 
    LotofSpuds 5.00-6.50 

Washington 

RedSpuds 
TinyReds 1.50-2.00 
BigReds 2.00-3.50 
BrownSpuds 
SomeSpuds 1.50-2.50 
MoreSpuds 3.00-3.50 
LotofSpuds 5.50-6.50 
BulkSpuds 1.00-2.50 

Long Island 
SomeSpuds 1.50-2.50 MoreSpuds 2.70-3.75 LotofSpuds 5.00-6.50 
etc... 

我包括不一致的縮進和行有意打破。這是一項政府行動。

但我需要一個函數,可以在愛達荷州查找「MoreSpuds」的價格,或者在華盛頓查找「TinyReds」的價格。我有一個暗示,這是一個正則表達式的工作,但我不知道如何搜索「愛達荷州」和「華盛頓」之間的多條線。

編輯:添加以下困難。一個特定的項目並不總是出現在一個給定的狀態。例如,華盛頓的「RedSpuds」可能會在另一個州的「RedSpuds」之前淘汰賽季。我需要在搜索到達下一個狀態之前結束搜索,如果該項目未列出,則完全不給我任何價格。

我也遇到了價格是用段落而不是列表寫成的情況。有點像最後一個例子,但實際的產品名稱更長,比如「一次打包的10磅5磅麻袋,10.00-10.50」,所以有些名稱會在兩行之間分開,這意味着任何地方都可能有換行符在名字的中間。

回答

1

使用DOTALL modifier (?s)使點也匹配甚至換行符。

>>> import re 
>>> s = """Potato Prices as of 24-SEP-2014 
... Idaho 
... BrownSpuds 
... SomeSpuds 1.90-3.00 mostly 2.00-2.50 
... MoreSpuds 2.50-3.50 
... LotofSpuds 5.00-6.50 
... 
... Washington 
... 
... RedSpuds 
... TinyReds 1.50-2.00 
... BigReds 2.00-3.50 
... BrownSpuds 
... SomeSpuds 1.50-2.50 
... MoreSpuds 3.00-3.50 
... LotofSpuds 5.50-6.50 
... BulkSpuds 1.00-2.50 
... 
... Long Island 
... SomeSpuds 1.50-2.50 MoreSpuds 2.70-3.75 LotofSpuds 5.00-6.50""" 

要獲得MoreSpuds價格在Idaho

>>> m = re.search(r'(?s)\bIdaho\n*(?:(?!\n\n).)*?MoreSpuds\s+(\S+)', s) 
>>> m.group(1) 
'2.50-3.50' 

要獲得的Washington 價格,

>>> m = re.search(r'(?s)\bWashington\n*(?:(?!\n\n).)*?TinyReds\s+(\S+)', s) 
>>> m.group(1) 
'1.50-2.00' 

DEMO

霸ttern說明:

  • (?s) DOTALL修飾符。
  • \b單詞與非單詞字符匹配的單詞邊界。
  • Washington城市名稱。
  • \n*匹配零個或多個換行符。
  • (?:(?!\n\n).)*?非捕獲組內的負向視圖斷言匹配任何但不是\n\n(空白行)。在*之後?強制正則表達式引擎做盡可能短的匹配。
  • 產品名稱。
  • \s+匹配一個或多個空格字符。
  • (\S+)以下一個或多個非空格字符被捕獲到組1
+0

感謝您的詳細解釋。例如,我忘了還提到,有時某個特定物品將不再列在某個州的名單上,例如,明尼蘇達州的紅色馬鈴薯比在華盛頓的時間早。如何確保搜索在達到下一個狀態之前結束? – 2014-09-26 16:25:33

+0

狀態必須以起始錨點或空行開始,因此我們確保搜索在到達下一個狀態之前結束。 – 2014-09-26 16:34:56