Лучший способ перебрать записи, разделенные двумя ключевыми словами? - PullRequest
1 голос
/ 20 ноября 2010

Текстовое содержимое файла:

&CRB  A='test1'   B=123,345, 678   &END
Misc text potentially between entries ...
&CRB  A='test2'   
             B=788, 345, 3424   &END
&CRB  A='test3'   
             B=788, 345, 3424   &END
&CRB  A='test4' B=788, 345, 3424   &END

Каков наиболее эффективный способ перебора записей между ключевыми словами?Обратите внимание, что некоторые записи охватывают строки.Желательно что-то вроде следующего -

f = open(filename)
for entry in f:
    - do something with entry

Конечно, это не так просто.Но есть ли предложения о прямом способе перебора всех записей, разделенных двумя ключевыми словами.

Ответы [ 3 ]

4 голосов
/ 20 ноября 2010

Предполагая, что запись представляет собой весь текст между парами &CRB и &END, вы можете вытянуть текст между ними примерно так:

import re

# the regular expression treats newlines as a regular character, so the
# multiline entries are okay. It's non-greedy, so it gets individual entries.
pat = re.compile(r'&CRB(.+?)&END',  re.DOTALL)

s = ''' &CRB  A='test1'   B=123,345, 678   &END
Misc text potentially between entries ...
&CRB  A='test2'   
             B=788, 345, 3424   &END
&CRB  A='test3'   
             B=788, 345, 3424   &END
&CRB  A='test4' B=788, 345, 3424   &END'''

for entry in pat.findall(s):
   # do something with each entry
   print entry

печатает это:

 A='test1'   B=123,345, 678   
  A='test2'   
             B=788, 345, 3424   
  A='test3'   
             B=788, 345, 3424   
  A='test4' B=788, 345, 3424  

... ваша проблема - очистить и интерпретировать содержимое каждой из этих записей ...

1 голос
/ 21 ноября 2010

Я бы использовал re.finditer вместо re.findall, поскольку мы не знаем, как размер файла, анализирующего его за один раз, может быть слишком много памяти в то время как наличие итератора, выдающего результаты, не позволит программе потреблять слишком много оперативной памяти.

Так что я думаю, что лучшее решение - , опубликованное bgporter , использующее pat.finditer вместо pat.findall в цикле for. finditer возвращает MatchObject s, а не строки, чтобы получить соответствующую строку, просто вызовите .group():

for entry in pat.finditer(s):
    entry_text = entry.group()
    #do something with entry_text.
0 голосов
/ 20 ноября 2010

Я бы прочитал в файле, использовал filecontents.split ('& CRB'), а затем проанализировал каждую строку с помощью регулярных выражений (см. re модуль).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...