В Python 2.6 или лучше:
def doit(inf, ouf, thestring, separator='SEPARATOR\n'):
thestring += '\n'
for line in inf:
# here we're always at the start-of-block separator
assert line == separator
blockid = next(inf)
if blockid == thestring:
# found block of interest, use enumerate to count its lines
for c, line in enumerate(inf):
if line == separator: break
assert line == separator
# emit results and terminate function
ouf.writelines((separator, thestring, '(%d)' % c, separator))
inf.close()
ouf.close()
return
# non-interesting block, just skip it
for line in inf:
if line == separator: break
В более старых версиях Python вы можете сделать почти то же самое, но измените строку blockid = next(inf)
на blockid = inf.next()
.
Предположения здесь заключаются в том, что входной и выходной файлы открываются вызывающей стороной (которая также принимает интересные значения thestring
и, необязательно, separator
), но задача этой функции - закрыть их (например, для максимальной простоты). использования в качестве фильтра конвейера, с inf sys.stdin
и ouf sys.stdout
); легко настроить, если нужно, конечно.
Удаление assert
s ускорит его микроскопически, но мне нравится их роль «проверки работоспособности» (и они также могут помочь понять логику потока кода).
Ключом к этому подходу является то, что файл является итератором (из строк), и итераторы могут быть расширены в нескольких местах (так что мы можем иметь несколько операторов for
или специальные вызовы "продвигать итератор", такие как next(inf)
и они правильно сотрудничают).