我有一个文件,其中包含一些代码行,后跟一个字符串模式。我需要在文件一中包含字符串模式的行之前写下所有内容,在文件二中写下字符串模式之后的所有内容:
例如(文件内容)
- 代码行 1
- 代码行 2
- 字符串模式
- 代码行 3
输出应该是带有代码行 1、代码行 2 的文件 1 和带有代码行 3 的文件 2。
对写文件比较熟悉,可惜不知道如何判断字符串模式前后的内容。
如果输入文件适合内存,最简单的解决方案是使用str.partition()
:
with open("inputfile") as f:
contents1, sentinel, contents2 = f.read().partition("Sentinel text\n")
with open("outputfile1", "w") as f:
f.write(contents1)
with open("outputfile2", "w") as f:
f.write(contents2)
这假设您知道分隔这两个部分的行的确切文本。
这种方法类似于Lev 的itertools
方法,但因为它很有趣而使用。
dont_break = lambda l: l.strip() != 'string_pattern'
with open('input') as source:
with open('out_1', 'w') as out1:
out1.writelines(itertools.takewhile(dont_break, source))
with open('out_2', 'w') as out2:
out2.writelines(source)
如果需要,您可以用正则表达式或其他任何东西替换 dont_break 函数。
with open('data.txt') as inf, open('out1.txt','w') as of1, open('out2.txt','w') as of2:
outf = of1
for line in inf:
if 'string pattern' in line:
outf = of2
continue # prevent output of the line with "string pattern"
outf.write(line)
将处理大文件,因为它逐行工作。假设string pattern
在输入文件中只出现一次。如果整个文件可以放入内存,我最喜欢这种str.partition()
方法(这可能不是问题)
使用with
确保文件在您完成或遇到异常时自动关闭。
一个天真的例子(不会像 Sven 那样将文件加载到内存中):
with open('file', 'r') as r:
with open('file1', 'w') as f:
for line in r:
if line == 'string pattern\n':
break
f.write(line)
with open('file2', 'w') as f:
for line in r:
f.write(line)
这假设'string pattern'
在输入文件中发生一次。
如果模式不是固定字符串,则可以使用该re
模块。
一个更有效的答案,它将处理大文件并消耗有限的内存..
inp = open('inputfile')
out = open('outfile1', 'w')
for line in inp:
if line == "Sentinel text\n":
out.close()
out = open('outfile2', 'w')
else:
out.write(line)
out.close()
inp.close()
不超过三行:
with open('infile') as fp, open('of1','w') as of1, open('of2','w') as of2:
of1.writelines(iter(fp.readline, sentinel))
of2.writelines(fp)
你需要类似的东西:
def test_pattern(x):
if x.startswith('abc'): # replace this with some exact test
return True
return False
found = False
out = open('outfile1', 'w')
for line in open('inputfile'):
if not found and test_pattern(line):
found = True
out.close()
out = open('outfile2', 'w')
out.write(line)
out.close()
用适用于您的模式的测试替换该行(如有必要,使用来自 re 的模式匹配,但任何找到分隔线的东西都可以)。