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

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

这是整个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!上的gsub! 不正确的? 我做错了什么吗?

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

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

紧接在此之前或之后:

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

正如下面的DMG所说,只是覆盖文件并不是特别偏执,因为你可能会在写入过程中被中断并丢失数据。 如果你想成为偏执狂(我们所有人都应该是因为他们真的想要我们),那么你想写一个临时文件然后做一个primefaces重命名来替换原来的新文件。 重命名通常仅在您保留在单个文件系统中时才起作用,因为无法保证OS的临时目录(默认情况下Tempfile使用该目录)与modRav位于同一文件系统上,因此File.rename可能不是一个选项除非采取预防措施,否则为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. 没有gsub! 在post中(标题和问题除外)。 我实际上建议不要使用gsub! ,而是使用gsub的结果 – 避免可变性可以帮助减少一些微妙的错误。

  2. 从文件流读取 String的行是一个副本 ,修改它不会影响文件的内容。 (一般的方法是读取一条线,处理线,然后写入线。或者一次完成所有操作:读取所有线,处理所有线,写入所有处理过的线。在任何一种情况下,都没有任何东西被写回文件在post中的代码;-)

快乐的编码。

你没有使用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