部分之间的Python多行正则表达式搜索

时间:2014-09-25 02:03:48

标签: python regex multiline

我正在尝试对来自在线纯文本政府报告的数据进行排序,该报告看起来像这样:

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"在华盛顿。我有一个暗示这是Regex的工作,但我无法弄清楚如何在" Idaho"之间搜索多条线路。和"华盛顿"。

编辑:添加以下难度。特定项目并不总是存在于给定状态。例如," RedSpuds"在华盛顿,可能会在赛季结束之前退出赛季,并且#34; RedSpuds"在另一个州。我需要搜索在它到达下一个状态之前结束,如果项目没有列出,我根本没有价格。

我还遇到了一个案例,其中价格是用段落而不是列表写的。有点像最后一个例子,但实际的产品名称要长得多,例如"一个打包10个5磅的麻袋sz A 10.00-10.50"因此,一些名称在行之间分开,这意味着名称中间的任何位置都可能有换行符。

1 个答案:

答案 0 :(得分: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"""

要获得MoreSpudsIdaho的价格,

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

要获得TinyRedsWashington的价格,

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

DEMO

模式说明:

  • (?s) DOTALL修饰符。
  • \b在单词和非单词字符之间匹配的单词边界。
  • Washington城市名称。
  • \n*匹配零个或多个换行符。
  • (?:(?!\n\n).)*?非捕获组内的这种否定前瞻声明匹配任何但不是\n\n(空白行)。 ?迫使正则表达式引擎进行尽可能短的匹配后*
  • TinyReds产品名称。
  • \s+匹配一个或多个空格字符。
  • (\S+)将一个或多个非空格字符捕获到组1中。