Python 如何仅在某个字符串之后读取文本文件中的行?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27805919/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 02:18:53  来源:igfitidea点击:

How to only read lines in a text file after a certain string?

pythonstringfile

提问by Brian Zelip

I'd like to read to a dictionary all of the lines in a text file that come after a particular string. I'd like to do this over thousands of text files.

我想将文本文件中特定字符串之后的所有行读入字典。我想对数千个文本文件执行此操作。

I'm able to identify and print out the particular string ('Abstract') using the following code (gotten from this answer):

我可以'Abstract'使用以下代码(从这个答案中获得)识别并打印出特定的字符串 ( ):

for files in filepath:
    with open(files, 'r') as f:
        for line in f:
            if 'Abstract' in line:
                print line;

But how do I tell Python to start reading the lines that only come after the string?

但是我如何告诉 Python 开始读取只出现在字符串之后的行?

采纳答案by Padraic Cunningham

just start another loop when you reach the line you want to start from :

当您到达要开始的行时,只需开始另一个循环:

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

A file object is it's own iterator, so when we reach the line with Abstract in it we continue our iteration from that line until we have consumed the iterator.

一个文件对象是它自己的迭代器,所以当我们到达包含 Abstract 的那一行时,我们从那一行继续迭代,直到我们用完迭代器。

A simple example:

一个简单的例子:

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

You can also use itertools.dropwhileto consume the lines up to the point you want.

您还可以使用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)

回答by Kroltan

Use a boolean to ignore lines up to that point:

使用布尔值忽略到该点的行:

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

回答by Henry Keiter

Just to clarify, your code already"reads" all the lines. To start "paying attention" to lines after a certain point, you can just set a boolean flag to indicate whether or not lines should be ignored, and check it at each line.

只是为了澄清,您的代码已经“读取”了所有行。要在某个点之后开始“注意”行,您可以设置一个布尔标志来指示是否应忽略行,并在每一行检查它。

pay_attention = False
for line in f:
    if pay_attention:
        print line
    else:  # We haven't found our trigger yet; see if it's in this line
        if 'Abstract' in line:
            pay_attention = True


If you don't mind a little more rearranging of your code, you can also use two partial loops instead: one loop that terminates once you've found your trigger phrase ('Abstract'), and one that reads all following lines. This approach is a little cleaner (and a very tiny bit faster).

如果您不介意重新排列代码,您也可以使用两个部分循环:一个循环在您找到触发短语 ( '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's iterator starts up again right where we left it.
    print line

The reason this works is that the file object returned by openbehaves like a generator, rather than, say, a list: it only produces values as they are requested. So when the first loop stops, the file is left with its internal position set at the beginning of the first "unread" line. This means that when you enter the second loop, the first line you see is the first line after the one that triggered the break.

这样做的原因是返回的文件对象open表现得像一个generator,而不是一个列表:它只在请求时产生值。因此,当第一个循环停止时,文件的内部位置设置在第一个“未读”行的开头。这意味着当您进入第二个循环时,您看到的第一行是触发break.

回答by Jon Clements

You can use itertools.dropwhileand itertools.islicehere, a pseudo-example:

您可以使用itertools.dropwhileitertools.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

回答by Steve Jessop

Making a guess as to how the dictionary is involved, I'd write it this way:

猜测字典是如何涉及的,我会这样写:

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)

So for each file, your dictionary contains a tuple of lines.

因此,对于每个文件,您的字典都包含一个行元组。

This works because the loop reads up to and including the line you identify, leaving the remaining lines in the file ready to be read from f.

这是有效的,因为循环读取并包括您标识的行,使文件中的其余行准备好从f.

回答by eguaio

To me, the following code is easier to understand.

对我来说,下面的代码更容易理解。

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'