我正在尝试对来自在线纯文本政府报告的数据进行排序,该报告看起来像这样:
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"因此,一些名称在行之间分开,这意味着名称中间的任何位置都可能有换行符。
答案 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"""
要获得MoreSpuds
中Idaho
的价格,
>>> m = re.search(r'(?s)\bIdaho\n*(?:(?!\n\n).)*?MoreSpuds\s+(\S+)', s)
>>> m.group(1)
'2.50-3.50'
要获得TinyReds
中Washington
的价格,
>>> m = re.search(r'(?s)\bWashington\n*(?:(?!\n\n).)*?TinyReds\s+(\S+)', s)
>>> m.group(1)
'1.50-2.00'
模式说明:
(?s)
DOTALL修饰符。\b
在单词和非单词字符之间匹配的单词边界。Washington
城市名称。\n*
匹配零个或多个换行符。(?:(?!\n\n).)*?
非捕获组内的这种否定前瞻声明匹配任何但不是\n\n
(空白行)。 ?
迫使正则表达式引擎进行尽可能短的匹配后*
。TinyReds
产品名称。\s+
匹配一个或多个空格字符。(\S+)
将一个或多个非空格字符捕获到组1中。