如何阅读第 2 行和第 3 行,然后每隔 5 行阅读:第 2、3、7、8、12、13 等

How to Read the 2nd and 3rd line then Every Fifth Line After: 2nd, 3rd, 7th, 8th, 12th, 13th, etc

我正在尝试从 python.

中的文本文件中读取某些行

我的文本文件:

Data Set    
for this Event    
d1: p, t, h = 9, 12, 30    
d2: p, t, h = 12, 22, 11    
Data Set     
for this Event    
d1: p, t, h = 9, 12, 30    
d2: p, t, h = 12, 22, 11

etc. 

如何读取第 2 行和第 3 行,然后是第 7、8、12、13 行,以便我只读取包含数据的行并跳过具有此事件数据集的行。

这是我尝试过的:

with open("d.txt") as f:

   for line2 in f.read().split("\n")[2::5]:
     print(line2)
   for line3 in f.read().split("\n")[3::5]:
     print(line3)
while line2:
   line = []
   line.append(line2)
   print(line)

但这只给我第 2、7、12、17 等行。我没有得到第 2、3、7、8、12、13 等行,我做错了什么?如果我改写 line.append(line3),则会收到以下错误:

Traceback (most recent call last):
  File "write.py", line 9, in <module>
    line.append(line3)
NameError: name 'line3' is not defined

任何指导将不胜感激!

编辑:查看答案和评论后,我现在尝试将以下代码编写为我的代码:

from itertools import tee, islice
with open("d.txt") as f:
f1 = islice(f, 2, None, 5)
f2 = islice(f ,3, None, 5)

for l1, l2 in f1, f2:
    #print(f "{l1} --- {l2}")
    pass

但是,我现在收到一个错误,我不明白为什么会这样: 追溯(最近一次通话): 文件 "write.py",第 6 行,位于 对于 f1、f2 中的 l1、l2: ValueError:要解压的值太多

我现在仍然不知道如何修复此代码。任何进一步的指南将不胜感激!

f.read() 耗尽了要从文件中读取的剩余字符的内部缓冲区。这意味着如果您连续调用 f.read() 两次,第一次调用会起作用,但第二次调用不会(它将 return 一个空字符串,因为文件已被第一次调用耗尽)。您必须使用 seek() 方法将内部字符光标放回文件的开头。或者,只需先阅读所有行,然后再做其余的事情。

with open("d.txt") as f:

    lines = f.readlines()

    for line2 in lines[2::5]:
        #...
    for line3 in lines[3::5]:
        #...

另一种方法是使用正则表达式来匹配和保留那些遵循您要查找的模式的行。

正如其他人所指出的,您没有得到预期答案的一个原因是您在第一次遍历生成器后消耗了它。

解决这个问题的一种方法是,您可以利用以下事实:您要读取的行号只有四个值,模 10。例如2, 3, 7, 8, 12, 13, 17, 18, ... 然后使用 enumerate 只读取您想要的行。

valid = {2, 3, 7, 8}

with open("file.txt", "r") as fh:
    for n, line in enumerate(fh.readlines()):
        if n % 10 in valid:
            print(line)

问题是文件对象 f 是一个 iterator,因此一旦你遍历它就会耗尽。

你可以像@user10987432 说的那样使用f.seek(0)回到开头,或者你可以使用itertools.tee()

itertools.tee() 允许您从单个迭代器创建多个独立的迭代器。

from itertools import tee, islice
with open('foo') as f:
    f1, f2 = tee(f)
    for l1, l2 in zip(islice(f1, 2, None, 5), islice(f2, 3, None, 5)):
        print(f'{l1}  ---  {l2}')

将打印

d1: p, t, h = 9, 12, 30
  ---  d2: p, t, h = 12, 22, 11

d1: p, t, h = 9, 12, 30
  ---  d2: p, t, h = 12, 22, 11

\n 不会自动剥离(至少在我的测试中)所以你需要自己处理它

到 select 行 [2, 3, 7, 8, 12, 13, 17, 18...] 您可以检查它们的索引模 5 是否等于 2 或 3。

因此,给定行索引 i,

if (i % 5 == 2 or i % 5 == 3):
    # append row to list of relevant rows
然而,

Python 索引从 0 开始,因此您实际需要的是索引对 5 取模等于 1 或 2 的行。

if (i % 5 == 1 or i % 5 ==2):
    # append row