为什么不gsub!改变我的文件?

时间:2011-07-30 06:14:58

标签: ruby

我正在尝试对目录中的所有文本文件执行简单的查找/替换,通过在行之前插入字符串(在本例中为“raven was here”)来修改[RAVEN_START:的任何实例。

以下是整个ruby计划:

#!/usr/bin/env ruby
require 'rubygems'
require 'fileutils' #for FileUtils.mv('your file', 'new location')

class RavenParser

  rawDir = Dir.glob("*.txt")
  count = 0
  rawDir.each do |ravFile|
    #we have selected every text file, so now we have to search through the file
    #and make the needed changes.
    rav = File.open(ravFile, "r+") do |modRav|
      #Now we've opened the file, and we need to do the operations.
        if modRav            
        lines = File.open(modRav).readlines
        lines.each { |line|
        if line.match /\[RAVEN_START:.*\]/ 
          line.gsub!(/\[RAVEN_START:/, 'raven was here '+line)
          count = count + 1
        end
        }
         printf("Total Changed: %d\n",count)
      else
         printf("No txt files found. \n")
      end
    end
    #end of file replacing instructions.
  end

  # S
end

程序运行并编译正常,但是当我打开文本文件时,文件中的任何文本都没有变化。 count正确递增(即,它等于所有文件中[RAVEN_START:的实例数),但实际替换未能发生(或至少不保存更改)。

gsub!上的语法不正确吗?我做错了吗?

3 个答案:

答案 0 :(得分:6)

您正在读取数据,更新数据,然后忽略将数据写回文件。你需要这样的东西:

# And save the modified lines.
File.open(modRav, 'w') { |f| f.puts lines.join("\n") }

紧接在此之前或之后:

printf("Total Changed: %d\n",count)

如下面DMG所述,只是覆盖文件并不是特别偏执,因为你可能会在写入过程中被中断并丢失数据。如果你想成为偏执狂(我们所有人都应该因为他们真的出来得到我们),那么你想写一个temporary file然后做一个原子重命名来取代原始文件是新文件。重命名通常仅在您保留在单个文件系统中时才起作用,因为无法保证操作系统的临时目录(默认情况下Tempfile使用)将与modRav位于同一文件系统上,因此{{除非采取预防措施,否则3 {}甚至可能不是Tempfile的选项。但Tempfile构造函数采用tmpdir参数,因此我们已保存:

modRavDir = File.dirname(File.realpath(modRav))
tmp       = Tempfile.new(modRav, modRavDir)
tmp.write(lines.join("\n"))
tmp.close
File.rename(tmp.path, modRav)

您可能希望将其添加到单独的方法中(或许safe_save(modRav, lines)),以避免进一步混乱。

答案 1 :(得分:5)

  1. 帖子中没有gsub!(标题和问题除外)。我实际上建议使用gsub!,而是使用gsub的结果 - 避免可变性可以帮助减少一些微妙的错误。

  2. 从文件流一个字符串的 copy 并修改它不会影响其内容文件。 (一般方法是读取一行,处理行,然后写行。或者一次完成所有操作:读取所有行,处理所有行,写入所有已处理的行。在任何一种情况下,都没有任何内容写回文件在帖子的代码中; - )

  3. 快乐的编码。

答案 2 :(得分:1)

您没有使用gsub!,而是使用gsubgsub!gsub个不同的方法,一个替换对象本身,另一个替换然后分别返回结果。

更改此

line.gsub(/\[RAVEN_START:/, 'raven was here '+line)

到此:

line.gsub!(/\[RAVEN_START:/, 'raven was here '+line)

或者这个:

line = line.gsub(/\[RAVEN_START:/, 'raven was here '+line)

有关详细信息,请参阅String#gsub