Как читать только строки в текстовом файле после определенной строки?

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

Я могу определить и распечатать конкретную строку ('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.