如何用python在大文件中对两个模式之间的行进行grep

2024-05-17 01:11:10 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个很大的文件,像这样:

[PATTERN1]
line1
line2
line3 
...
...
[END PATTERN]
[PATTERN2]
line1 
line2
...
...
[END PATTERN]

我需要在另一个文件中提取变量starter模式[PATTERN1]和另一个define模式[END pattern]之间的行,仅用于某些特定的starter模式。
例如:

[PATTERN2]
line1 
line2
...
...
[END PATTERN]

我已经做了同样的事情,用一个较小的文件,使用以下代码:

FILE=open('myfile').readlines()

newfile=[]
for n in name_list:
    A = FILE[[s for s,name in enumerate(FILE) if n in name][0]:]
    B = A[:[e+1 for e,end in enumerate(A) if 'END PATTERN' in end][0]]
    newfile.append(B)

其中“name_list”是一个包含我需要的特定启动模式的列表。

有效!!但我想有更好的方法来处理大文件,而不使用.readlines()命令。
有人能帮我吗?

非常感谢!


Tags: 文件nameinfor模式fileendpattern
3条回答

我想这和你的代码一样:

FILE=open('myfile').readlines()

newfile=[]

pattern = None
for line in FILE:
    if line[0] == "[" and line[-1] == "]":
        pattern = line[1:-1]
        if pattern == "END PATTERN":
            pattern = None
        continue
    elif pattern is not None and pattern in name_list:
        newfile.append(line)

这样你只需浏览一次所有的行,然后在浏览时填写你的列表。

考虑:

# hi
# there
# begin
# need
# this
# stuff
# end
# skip
# this

with open(__file__) as fp:
    for line in iter(fp.readline, '# begin\n'):
        pass
    for line in iter(fp.readline, '# end\n'):
        print line

打印“需要这些东西”

更灵活(例如允许重新模式匹配)的方法是使用itertools drop-and-takewhile:

with open(__file__) as fp:
    result = list(itertools.takewhile(lambda x: 'end' not in x, 
        itertools.dropwhile(lambda x: 'begin' not in x, fp)))

使用类似于

import re

START_PATTERN = '^START-PATTERN$'
END_PATTERN = '^END-PATTERN$'

with open('myfile') as file:
    match = False
    newfile = None

    for line in file:
        if re.match(START_PATTERN, line):
            match = True
            newfile = open('my_new_file.txt', 'w')
            continue
        elif re.match(END_PATTERN, line):
            match = False
            newfile.close()
            continue
        elif match:
            newfile.write(line)
            newfile.write('\n')

这将迭代文件,而不将其全部读入内存。它还直接写入新文件,而不是附加到内存中的列表。如果你的来源足够大,也可能成为一个问题。

显然,您可能需要对此代码进行许多修改;也许不需要regex模式来匹配开始/结束行,在这种情况下,可以用if 'xyz' in line之类的内容替换它。

相关问题 更多 >