你可以使用一个GROUPBY假设该部分通过启动#TYPE
线划定:
from itertools import groupby, chain
def get_sections(fle):
with open(fle) as f:
grps = groupby(f, key=lambda x: x.lstrip().startswith("#TYPE"))
for k, v in grps:
if k:
yield chain([next(v)], (next(grps)[1])) # all lines up to next #TYPE
你可以得到每节为你迭代:
In [13]: cat in.txt
#TYPE Lorem.Text.A
first
#TYPE Lorem.Text.B
second
#TYPE Lorem.Text.C
third
In [14]: for sec in get_sections("in.txt"):
....: print(list(sec))
....:
['#TYPE Lorem.Text.A\n', 'first\n']
['#TYPE Lorem.Text.B\n', 'second\n']
['#TYPE Lorem.Text.C\n', 'third\n']
如果没有其他行以#
然后单独将足以在startswith使用,有没有在你的模式复杂,所以它不是一个真正的正则表达式的用例。这也只是将一段文件一次不存储到整个文件中。
如果你没有前导空白,唯一的地方#
出现是TYPE之前可能就足够了就叫GROUPBY:
from itertools import groupby, chain
def get_sections(fle):
with open(fle) as f:
grps = groupby(f)
for k, v in grps:
if k:
yield chain([next(v)], (next(grps)[1])) # all lines up to next #TYPE
如果有一些元数据在一开始,你可以使用dropwhile跳过线直到我们打#Type
,然后就组:
from itertools import groupby, chain, dropwhile
def get_sections(fle):
with open(fle) as f:
grps = groupby(dropwhile(lambda x: not x.startswith("#"), f))
for k, v in grps:
if k:
yield chain([next(v)], (next(grps)[1])) # all lines up to next #TYPE
演示:
In [16]: cat in.txt
meta
more meta
#TYPE Lorem.Text.A
first
#TYPE Lorem.Text.B
second
second
#TYPE Lorem.Text.C
third
In [17]: for sec in get_sections("in.txt"):
print(list(sec))
....:
['#TYPE Lorem.Text.A\n', 'first\n']
['#TYPE Lorem.Text.B\n', 'second\n', 'second\n']
['#TYPE Lorem.Text.C\n', 'third\n']
我会检查你的建议。 –
@AdrianZ ..它肯定会工作,并避免在存储器中存储多个数据副本,如果你使用。阅读与re.split你将存储在内存中的数据的两个完整副本,如果您的文件很大可能不可能 –
它看起来非常好,我喜欢不浪费内存的想法。现在我没有从打印输出中获得输出,但我会继续测试一下,然后返回结果。 –