【问题标题】:Inserting lines to a file after a string match在字符串匹配后向文件插入行
【发布时间】:2014-10-28 22:27:40
【问题描述】:

我正在尝试在文件的行中搜索子字符串,并在找到的行之后立即插入类似的行。尽管使用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
带有 abc 的新行
带有 pqr 的新行
带有 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

【问题讨论】:

  • 如果mauris etiam quisque 重复怎么办?或者这是否只处理第一次出现并且应该break 之后?
  • 你为什么不知道如何在你的情况下使用fileinput?你尝试了什么,它是如何失败的?

标签: python python-2.7


【解决方案1】:

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

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()

【讨论】:

    【解决方案2】:

    一般不能插入到文件的中间。*

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

    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)
    

    请注意,os.replace 在 Python 2.7 中不存在。如果您不关心 Windows,则可以改用 os.rename。如果你这样做,我强烈建议在 PyPI 上寻找 os.replace 的反向移植;至少有两个。否则,您必须了解 Windows 上的排他锁和原子移动的全部混乱情况。

    还有一些更高级别的库可以为您完成整个过程。 (我写了一个名为 fatomic 的代码,我认为它可以作为很好的示例代码,但我不确定如果没有更多测试,我是否会相信它用于生产代码。我敢肯定,如果你搜索 PyPI,你可以找到其他替代方案.)


    当然还有其他选择:

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

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

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


    * 为什么我在那里说“一般”?好吧,最终,文件系统必须有某种方式在文件中间插入一个新块。一些文件系统会将其暴露给用户级别。一些旧平台曾经在此之上构建了用户级功能,例如 Apple 上的“随机访问文本文件”][ ProDOS 或我在 VMS 中忘记的东西。因此,您永远不能插入文件的中间,这并不是真的。在您关心的每种情况下都是如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 2018-02-02
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 2012-11-24
      相关资源
      最近更新 更多