2014-09-25 5 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» в Вашингтоне. У меня есть подозрение, что это работа для Regex, но я не могу понять, как искать несколько строк между «Айдахо» и «Вашингтоном».

EDIT: Добавление следующей трудности. Отдельный элемент не всегда присутствует в определенном состоянии. Например, «RedSpuds» в Вашингтоне может выйти за сезон до «RedSpuds» в другом штате. Мне нужно, чтобы поиск заканчивался до того, как он достигнет следующего состояния, не давая мне никакой цены, если элемент не указан.

Я также столкнулся с ситуацией, когда цены были написаны в абзаце вместо списка. Похоже на последний пример, но фактические названия продуктов намного длиннее, например «Один упакованный 10 5-фунтовых мешков sz A 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

Спасибо за подробное объяснение. Я забыл также упомянуть, что иногда данный предмет больше не будет указан в штате, красный картофель выходит из сезона в Миннесоте раньше, чем в Вашингтоне, например.Как убедиться, что поиск заканчивается до достижения следующего состояния? –

+0

Перед состоянием должен стоять стартовый якорь или пустая строка. Таким образом, мы гарантируем, что поиск заканчивается до достижения следующего состояния. –

Смежные вопросы