在字符串匹配后将行插入文件

时间:2014-10-28 22:27:41

标签: python python-2.7

我试图在文件的行内搜索子字符串,并在找到的行之后立即插入类似的行。虽然使用fileinput方法有类似的解决方案,但在我的案例中我无法弄清楚如何使用它。

以下是我的尝试:

list = ["abc", "pqr", "xyz"]

inputfile = open (somefile.txt, 'a+')
for line in <inputfile>:    
    if 'stringstosearch' in line:
       for <item> in list:
               new_line = "new_line with %s" %(item)        
               inputfile.write(new_line + "\n") 
    break
inputfile.close()

例如,如果文本文件是:

  

Torquent scelerisque aptent hac rhoncus vel
  Turpis vestibulum tellus laoreet mollis conubia facilisis tempor nec semper
  在mi mauris etiam quisque sem congue est velit lacus convallis amet ante ad
  整数maecenas semper quisque nisi hendrerit,libero feugiat cursus euismod accumsan
  Dui sed magna vivamus augue ac quisque ac mauris torquent eros taciti
  Conubia curae vel himenaeos dictumst sed at

string to search = "mauris etiam quisque"
list = ["abc", "pqr", "xyz" ]

文件写入后的预期输出:

  

Torquent scelerisque aptent hac rhoncus vel
  Turpis vestibulum tellus laoreet mollis conubia facilisis tempor nec semper
  在mi mauris etiam quisque sem congue est velit lacus convallis amet ante ad
  new_line with abc
  new_line with pqr
  new_line with xyz
  整数maecenas semper quisque nisi hendrerit,libero feugiat cursus euismod accumsan
  Dui sed magna vivamus augue ac quisque ac mauris torquent eros taciti
  Conubia curae vel himenaeos dictumst sed at

2 个答案:

答案 0 :(得分:3)

您通常无法插入文件的中间。*

对此的通用解决方案是复制到新文件,在复制过程中插入,然后将新文件移到旧文件之上。例如:

with tempfile.NamedTemporaryFile('w', delete=False) as outfile:
    with open(inpath) as infile, 
        for line in infile:
            outfile.write(line)
            if needs_inserting_after(line):
                outfile.write(stuff_to_insert_after(line))
os.replace(outfile.name, inpath)

请注意,{2.7}中不存在os.replace。如果您不关心Windows,则可以使用os.rename代替。如果你这样做,我强烈建议在PyPI上寻找os.replace的后端;至少有两个。否则,您必须了解Windows上的独占锁和原子移动的整个混乱。

还有一些更高级别的库可以为您提供全部内容。 (我写了一篇名为fatomic的文章,我认为它是一个很好的示例代码,但是我不确定我是否会在没有更多测试的情况下信任生产代码。我确定是否你搜索PyPI你可以找到其他替代品。)


当然还有其他选择:

您可以将原始文件移动到备份路径,然后将其复制到正常路径的新文件中,而不是在临时路径上复制到新文件,然后在事后移动。如果您在中间失败,这样做的缺点是会留下半个文件,但不需要处理Windows上的独占锁定问题。这实际上是fileinput.FileInput inplace=True为{{1}}自动化的。

您可以将整个文件读入内存,在内存中处理它,然后将整个文件写回。这样做的好处是简单易用,不需要任何额外的文件,并且意味着如果任何人有文件句柄(而不是路径名),他们会在你完成后看到新版本。但最后一个可能是一个劣势。当然,这意味着您需要足够的内存来同时保存所有数据。

最后,在写入N个字节之前,您始终可以将整个文件从当前位置向上移动N个字节。这具有上述两个方面的大部分优点,但它也很麻烦和缓慢。


*为什么我说&#34;一般&#34;那里?好吧,最终,文件系统必须有一些方法在文件中间插入一个新块。一些文件系统会将其暴露给用户级别。一些较旧的平台过去常常在此基础上构建用户级功能,例如&#34;随机访问文本文件&#34;在Apple] [ProDOS或我忘记在VMS中的东西。因此,您无法插入文件中间并不是真的。在你关心的每一种情况下都是如此。

答案 1 :(得分:3)

你不能只插入文件的中间,所以第一次完全读取文件,对于小文件。然后在写入模式下打开同一个文件,并在找到字符串时附加。

list = ["abc", "pqr", "xyz"]

inputfile = open('somefile.txt', 'r').readlines()
write_file = open('somefile.txt','w')
for line in inputfile:
    write_file.write(line)
    if 'stringstosearch' in line:
       for item in list:
            new_line = "new_line with %s" %(item)        
            write_file.write(new_line + "\n") 
write_file.close()