Пиковый следующий символ в файле
Мне нужно прочитать файл в 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
Вы, кажется, не используете номера строк, поэтому я избавился от перечисления