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



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

[PATTERN1]第 1 行第 2 行3号线......[结束模式][PATTERN2]第 1 行第 2 行......[结束模式]

我需要在另一个文件中提取变量启动模式 [PATTERN1] 和另一个定义模式 [END PATTERN] 之间的线条,仅适用于某些特定的启动模式。
例如:

[PATTERN2]第 1 行第 2 行......[结束模式]

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

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() 命令。
有人可以帮助我吗?

多谢!

考虑:

# hi
# there
# begin
# need
# this
# stuff
# end
# skip
# this
with open(__file__) as fp:
    for line in iter(fp.readline, '# beginn'):
        pass
    for line in iter(fp.readline, '# endn'):
        print line

打印"需要这些东西"

更灵活的(例如,允许重新模式匹配)是使用迭代工具 drop- 和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')

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

显然,您可能需要对此代码进行许多修改;也许不需要正则表达式模式来匹配开始/结束行,在这种情况下,将其替换为类似if 'xyz' in line

我会选择基于生成器的解决方案

#!/usr/bin/env python    
start_patterns = ('PATTERN1', 'PATTERN2')
end_patterns = ('END PATTERN')
def section_with_bounds(gen):
  section_in_play = False
  for line in gen:
    if line.startswith(start_patterns):
      section_in_play = True
    if section_in_play:
      yield line
    if line.startswith(end_patterns):
      section_in_play = False
with open("text.t2") as f:
  gen = section_with_bounds(f)
  for line in gen:
    print line

我认为这与你的代码做同样的事情:

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)

这样,您只需浏览一次所有行,并随时填写列表。

我是一个新的 python 程序员,所以我只能勉强理解你的解决方案,但似乎有很多不必要的迭代正在进行。 首先读取文件,然后针对 name_list 中的每个项目循环访问文件一次。 另外,我不知道您是否打算稍后迭代newfile以实际将其写入文件。

以下是我的做法,尽管我意识到这不是最pythonic的解决方案。 不过,您只会循环访问该文件一次。 (作为免责声明,我没有对此进行测试。

patterns = {'startPattern1':"endPattern1", 'startPattern2':"endPattern2", 'startPattern3':"endPattern3"}
fileIn = open(filenameIn, 'r')
fileOut = open(filenameOut, 'w')
targetEndPattern = None
for line in fileIn:
   if targetEndPattern is not None:
       if line == targetEndPattern:
           targetEndPattern = None
       else:
           fileOut.write(line + "n")
   elif line in patterns:
       targetEndPattern = patterns[line]

编辑:如果您期望按特定顺序排列模式,则必须修改此解决方案。 我写这篇文章的假设是,模式的顺序无关紧要,但每个开始模式都与特定的结束模式匹配。

最新更新