Как читать только строки в текстовом файле после определенной строки?
Я хотел бы прочитать в словарь все строки в текстовом файле, которые следуют после определенной строки. Я хотел бы сделать это более тысячи текстовых файлов.
Я могу определить и распечатать конкретную строку ('Abstract'
), используя следующий код (полученный из этого ответа):
for files in filepath:
with open(files, 'r') as f:
for line in f:
if 'Abstract' in line:
print line;
Но как мне сказать Python начать читать строки, которые идут только после строки?
Ответы
Ответ 1
просто запустите другой цикл, когда вы достигнете линии, из которой вы хотите начать:
for files in filepath:
with open(files, 'r') as f:
for line in f:
if 'Abstract' in line:
for line in f: # now you are at the lines you want
# do work
Файловый объект - это собственный итератор, поэтому, когда мы достигаем строки с абстрактным в нем, мы продолжаем нашу итерацию с этой строки, пока не уничтожим итератор.
Простой пример:
gen = (n for n in xrange(8))
for x in gen:
if x == 3:
print("starting second loop")
for x in gen:
print("In second loop",x)
else:
print("In first loop", x)
In first loop 0
In first loop 1
In first loop 2
starting second loop
In second loop 4
In second loop 5
In second loop 6
In second loop 7
Вы также можете использовать itertools.dropwhile, чтобы использовать линии до нужной вам точки.
from itertools import dropwhile
for files in filepath:
with open(files, 'r') as f:
dropped = dropwhile(lambda _line: "Abstract" not in _line, f)
next(dropped,"")
for line in dropped:
print(line)
Ответ 2
Используйте логическое значение для игнорирования строк до этой точки:
found_abstract = False
for files in filepath:
with open(files, 'r') as f:
for line in f:
if 'Abstract' in line:
found_abstract = True
if found_abstract:
#do whatever you want
Ответ 3
Здесь вы можете использовать itertools.dropwhile
и itertools.islice
, псевдо-пример:
from itertools import dropwhile, islice
for fname in filepaths:
with open(fname) as fin:
start_at = dropwhile(lambda L: 'Abstract' not in L.split(), fin)
for line in islice(start_at, 1, None): # ignore the line still with Abstract in
print line
Ответ 4
Чтобы уточнить, ваш код уже "читает" все строки. Чтобы начать "обращать внимание" на строки после определенного момента, вы можете просто установить булевский флаг, чтобы указать, следует ли игнорировать строки или проверять их в каждой строке.
pay_attention = False
for line in f:
if pay_attention:
print line
else: # We haven't found our trigger yet; see if it in this line
if 'Abstract' in line:
pay_attention = True
Если вы не возражаете немного переупорядочить свой код, вы также можете использовать две частичные петли: один цикл, который заканчивается после того, как вы нашли триггерную фразу ('Abstract'
), и одну, которая читает все следующие линий. Этот подход немного чище (и очень маленький бит быстрее).
for skippable_line in f: # First skim over all lines until we find 'Abstract'.
if 'Abstract' in skippable_line:
break
for line in f: # The file iterator starts up again right where we left it.
print line
Причина этого в том, что объект файла, возвращаемый open
, ведет себя как generator, а не, скажем, список: он только производит значения по мере их запроса. Поэтому, когда первый цикл останавливается, файл остается со своим внутренним положением, установленным в начале первой "непрочитанной" строки. Это означает, что когда вы вводите второй цикл, первая строка, которую вы видите, является первой строкой после той, которая вызвала break
.
Ответ 5
Мне легче понять следующий код.
with open(file_name, 'r') as f:
while not 'Abstract' in next(f):
pass
for line in f:
#line will be now the next line after the one that contains 'Abstract'
Ответ 6
Сделав предположение о том, как задействован словарь, я напишу его так:
lines = dict()
for filename in filepath:
with open(filename, 'r') as f:
for line in f:
if 'Abstract' in line:
break
lines[filename] = tuple(f)
Итак, для каждого файла ваш словарь содержит кортеж строк.
Это работает, потому что цикл считывает и включает указанную строку, оставляя оставшиеся строки в файле готовыми к чтению из f
.