使用python将特定行从一个文件写入另一个文件
我有大约200个短文本文件(50kb),它们都有相似的格式。我想在每个文件中找到一行,其中包含某个字符串,然后将该行加上接下来的三行(但不是文件中的其余行)写入另一个文本文件。为了做到这一点,我尝试自学python,并编写了一个非常简单和粗糙的小脚本来尝试这一点。我正在使用版本2.6.5,并从Mac终端运行脚本:使用python将特定行从一个文件写入另一个文件,python,Python,我有大约200个短文本文件(50kb),它们都有相似的格式。我想在每个文件中找到一行,其中包含某个字符串,然后将该行加上接下来的三行(但不是文件中的其余行)写入另一个文本文件。为了做到这一点,我尝试自学python,并编写了一个非常简单和粗糙的小脚本来尝试这一点。我正在使用版本2.6.5,并从Mac终端运行脚本: #!/usr/bin/env python f = open('Test.txt') Lines=f.readlines() searchquery = 'am\n' i=0 w
#!/usr/bin/env python
f = open('Test.txt')
Lines=f.readlines()
searchquery = 'am\n'
i=0
while i < 500:
if Lines[i] == searchquery:
print Lines[i:i+3]
i = i+1
else:
i = i+1
f.close()
而且也不能让它起作用。如果有人能解释我做错了什么,或者就我应该尝试什么提出一些建议,我将非常感激。此外,如果你有任何建议,使搜索更好,我也会感谢这些。我一直在使用一个测试文件,其中我想要查找的字符串是行中唯一的文本,但在我的实际文件中,我需要的字符串仍然在行的开头,但后面跟着一堆其他文本,因此我认为我现在设置的方式也不会真正起作用
谢谢,如果这是一个超级基本的问题,我很抱歉 我认为您的问题在于底部文件的选项卡 您需要从if
行[i]
缩进到i=i+1
之后,例如:
while i < 500:
if Lines[i] == searchquery:
f2.write(Lines[i])
f2.write(Lines[i+1])
f2.write(Lines[i+2])
i = i+1
else:
i = i+1
当i<500时:
如果行[i]==搜索查询:
f2.写入(第[i]行)
f2.写入(行[i+1])
f2.写入(第[i+2]行)
i=i+1
其他:
i=i+1
正如@ajon所指出的,我认为您的代码除了缩进之外没有任何根本性的错误。有了固定的缩进,它对我很有效。然而,还有一些改进的机会
1)在Python中,迭代事物的标准方法是使用。当为循环使用时,您不需要定义循环计数器变量并自己跟踪它们来迭代。相反,你写了这样的东西
for line in lines:
print line
with open('test.txt') as f:
f.write('foo')
迭代字符串列表中的所有项并打印它们
2)在大多数情况下,这就是您的for
循环的外观。然而,在某些情况下,您确实希望跟踪循环计数。您的情况就是这种情况,因为您不仅需要这一行,还需要接下来的三行,因此需要使用计数器进行索引(lst[i]
)。对于这一点,它将返回一个项目列表及其索引,然后您可以在其上循环
for i, line in enumerate(lines):
print i
print line
print lines[i+7]
如果要像示例中那样手动跟踪循环计数器,有两件事:
3)应将i=i+1
移出if
和else
块。在这两种情况下都是这样,所以请将其放在if/else
后面。在您的情况下,else
块不再执行任何操作,可以消除:
while i < 500:
if Lines[i] == searchquery:
f2.write(Lines[i])
f2.write(Lines[i+1])
f2.write(Lines[i+2])
i = i+1
5)可作为一个用于为您关闭文件的工具。上下文管理器是一个相当高级的概念,但是如果已经为您提供了上下文管理器,那么它的使用非常简单。通过做这样的事情
for line in lines:
print line
with open('test.txt') as f:
f.write('foo')
该文件将以f
的形式打开并可供您使用块访问。离开块后,文件将自动关闭,因此不会忘记关闭文件
在你的情况下,你打开了两个文件。这可以通过使用两个和语句并嵌套它们来实现
with open('one.txt') as f1:
with open('two.txt') as f2:
f1.write('foo')
f2.write('bar')
或者,在Python2.7/Python3.x中,通过将两个上下文管理器嵌套在一个with
语句中:
with open('one.txt') as f1, open('two.txt', 'a') as f2:
f1.write('foo')
f2.write('bar')
6)根据创建文件的操作系统,行尾不同。在类UNIX平台上,它是\n
,在OSX之前的Mac使用\r
,Windows使用\r\n
。因此,行[i]==searchquery
将与Mac或Windows行结尾不匹配file.readline()
可以处理这三种情况,但由于它保留了行末尾的任何行结尾,因此比较将失败。这可以通过使用解决,它将去掉字符串开头和结尾的所有空白,并将不带行尾的搜索模式与以下模式进行比较:
searchquery = 'am'
# ...
if line.strip() == searchquery:
# ...
(使用file.read()
读取文件并使用将是另一种选择。)
但是,由于您提到您的搜索字符串实际上出现在行的开头,因此让我们使用:
7)Python的官方风格指南建议对类使用CamelCase
,对几乎所有其他内容(变量、函数、属性、方法、模块、包)使用小写下划线。因此,不要使用行
而使用行
。与其他观点相比,这无疑是一个次要的观点,但仍然值得及早纠正
因此,考虑到所有这些因素,我会像这样编写您的代码:
f1 = open('Test.txt')
f2 = open('Output.txt', 'a')
Lines=f1.readlines()
searchquery = 'am\n'
i=0
while i < 500:
if Lines[i] == searchquery:
f2.write(Lines[i])
f2.write(Lines[i+1])
f2.write(Lines[i+2])
i = i+1
else:
i = i+1
f1.close()
f2.close()
searchquery = 'am'
with open('Test.txt') as f1:
with open('Output.txt', 'a') as f2:
lines = f1.readlines()
for i, line in enumerate(lines):
if line.startswith(searchquery):
f2.write(line)
f2.write(lines[i + 1])
f2.write(lines[i + 2])
正如@TomK所指出的,所有这些代码都假设如果搜索字符串匹配,那么后面至少有两行。如果您不能依赖该假设,那么使用@poorsod suggered之类的块来处理这种情况是正确的方法。ajon给出了正确的答案,但只要您寻求指导,您的解决方案就不会利用Python提供的高级构造。那么:
searchquery = 'am\n'
with open('Test.txt') as f1:
with open(Output.txt, 'a') as f2:
Lines = f1.readlines()
try:
i = Lines.index(searchquery)
for iline in range(i, i+3):
f2.write(Lines[iline])
except:
print "not in file"
即使发生异常,这两个“with”语句也会在最后自动关闭文件
更好的解决方案是避免一次读取整个文件(谁知道它有多大?),而是使用文件对象上的迭代逐行处理:
with open('Test.txt') as f1:
with open(Output.txt, 'a') as f2:
for line in f1:
if line == searchquery:
f2.write(line)
f2.write(f1.next())
f2.write(f1.next())
所有这些都假设在目标行之外至少还有两行。您是否尝试过使用“Output.txt”以外的东西来避免任何与文件系统相关的问题
那么,在诊断这一问题时,是否有一个绝对路径来避免任何不可预见的问题呢
with open('Test.txt') as f1:
with open(Output.txt, 'a') as f2:
for line in f1:
if line == searchquery:
f2.write(line)
f2.write(f1.next())
f2.write(f1.next())
from itertools import slice
f1 = open('Test.txt')
f2 = open('Output.txt', 'a')
bunch = 500
lines = list(islice(f1, bunch))
f2.writelines(lines)
f1.close()
f2.close()