Пиковый следующий символ в файле

Мне нужно прочитать файл в Python, где разделы заключены в /*! для начала раздела и * для его конца:

/*!Text
 this text is to be printed, but it can expand
 several lines

 even empty lines, but they have to be printed in the same way they're encountered

 this until a * character is found
*

/*!Another section starts here
  whatever
*

Цель состоит в том, чтобы напечатать строки, как они встречаются в каждом разделе на данный момент (тогда мне придется сделать некоторую обработку). Чтобы прочитать файл в Python у меня есть что-то вроде этого:

# open file
with open(filename) as fh:

    fit = enumerate(iter(fh.readline, ''), start=1)

    # loop over lines
    for lino, line in fit:

        if line.startswith('/*!T'):
            lino, line = next(fit)
            print(lino, line)

Теперь, вместо того, чтобы печатать одну строку, я хотел бы напечатать как можно больше строк, пока новая строка не начнется со строки '/*!', В С можно использовать peak функция, так есть ли что-то эквивалентное в Python?

ОБНОВИТЬ

Так что я, возможно, добился определенного прогресса при открытии файла в двоичном режиме (я использую Python 3):

# open file
with open(filename, 'rb') as fh:

    fit = enumerate(iter(fh.readline, ''), start=1)

    # loop over lines
    for lino, line in fit:

        if not line:
            break

        if line.startswith('/*!T'):
            while True:

                lino, line = next(fit)
                print(str(line))

                char = fh.read(1)
                # back one character
                fh.seek(-1,1)
                if char == b'*':
                    break

Но мне кажется, что в Python должен быть очень компактный способ сделать это. Какие-либо предложения?

2 ответа

Решение

Я бы использовал регулярное выражение:

import re

def get_sections(filename):
  with open(filename) as f:
    data = f.read()
  return re.findall(r'(?sm)^/\*!(.*?)^\*', data)

for section in get_sections('inputfile.txt'):
  print section

В качестве альтернативы я мог бы создать функцию генератора, которая выдает только строки сечения:

def get_section_line(f):
  iterator = enumerate(f)
  for lno, line in iterator:
    if line.startswith("/*!"):
      yield lno, line.replace("/*!", "", 1)
      for lno, line in iterator:
        if line.startswith('*'):
          break
        yield lno, line

with open('inputfile.txt') as f:
  for lno, line in get_section_line(f):
    print "%04d %s"%(lno,line.rstrip('\n'))

Наконец, вот решение, которое поддерживает структуру раздела, в случае, если вы знаете, в каком разделе вы находитесь:

import itertools
def get_sections(f):
  it = enumerate(f)
  for lno, line in it:
    if line.startswith("/*!"):
      yield itertools.chain(
          [(lno,line.replace("/*!","",1))],
          itertools.takewhile(lambda i: not i[1].startswith('*'), it))

with open('inputfile.txt') as f:
  for secno, section in enumerate(get_sections(f)):
    for lno, line in section:
      print "%04d %04d %s"%(secno, lno,line.rstrip('\n'))

Вы непременно запутаете вещи, если будете читать и искать fh непосредственно в цикле, читая его из итератора.

Во всяком случае, это может дать вам некоторые идеи...

filename = 'test.txt'

with open(filename, 'r') as fh:
    for line in fh:
        if line.startswith('/*!'):
            while True:
                line = fh.next()
                if line[0] == '*':
                    #print '* End of section *'
                    break
                print line[:-1] #line already ends in \n

Вы, кажется, не используете номера строк, поэтому я избавился от перечисления

Другие вопросы по тегам