我有一个非常大的文件,像这样:
[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]
编辑:如果您期望按特定顺序排列模式,则必须修改此解决方案。 我写这篇文章的假设是,模式的顺序无关紧要,但每个开始模式都与特定的结束模式匹配。