如何用行号替换另一行的行?

时间:2015-09-11 19:41:53

标签: ruby

我有一个包含以下内容的文件:

My name is Chris
My name is Chris
My name is Chris

是否有文件功能来替换第n行,在这种情况下是文件中的第二行,所以新文件看起来像这样?

My name is Chris
My name is John
My name is Chris

我知道我可以逐行读取文件,并编写说明&#34的逻辑;如果num_line = 2则替换line"但我真的不想这样做。

2 个答案:

答案 0 :(得分:2)

你尝试做的事情是个坏主意。如果代码在中途崩溃,您的源/目标文件可能会损坏。

相反:

  1. 创建新文件。
  2. 使用foreach打开原始文件。
  3. 读一行,检查是否应该更改。如果是这样改变它。
  4. 将该行写入新文件。
  5. 关闭原始文件。
  6. 关闭新文件。
  7. 将原始文件重命名为安全的文件。
  8. 将新文件重命名为原始文件的名称。
  9. 遵循这些步骤有助于确保您的原始数据保持不变,直到最后的步骤#7和#8,然后将原始文件保存到备份并将新文件移动到旧文件中文件名。

    Ruby使用foreach的逐行IO比您尝试readreadlines更快,所以不要这样做。此外,readreadlines不具备可扩展性。如果原始文件很大,请考虑将其导入数据库,并使用DBM进行更改,然后将文件导出回磁盘。数据库附带的实用程序可以非常快速地加载和导出数据,并且可能运行得比基于纯Ruby的解决方案更快。

    您可以在不创建其他文件的情况下替换原始文件中的单个行,但执行此操作的代码非常混乱。使用line-IO和两个文件更容易,更安全,这使得这个过程非常简单。

    这个未经测试的代码就是这个过程的核心:

    File.open('file.new', 'w') do |fo|
      File.foreach('file.old') do |li|
        li = 'foo' if $. == 10
        fo.puts li
      end
    end
    

    $.是一个Ruby全局,包含最后读取行的行号,可以很容易地判断您是否想要更改该行。

答案 1 :(得分:0)

让我们创建一个 1

这样的文件
s =<<_
My name is Chris
My name is Chris
My name is Chris
and other stuff
_

FName = "my_file"

IO.write(FName, s)
  #=> 67 

如果文件不大,您可以写:

lines = File.readlines(FName)
  #=> ["My name is Chris\n",
  #    "My name is Chris\n",
  #    "My name is Chris\n",
  #    "and other stuff\n"] 

lines[1].sub!(/\bChris\b/, "John")
  #=> "My name is John\n" 

File.rename(FName, "#{FName}.bak")

open(FName, 'w') { |f| lines.each { |line| f << line } }
  #=> ["My name is Chris\n", "My name is John\n", "My name is Chris\n",
  #    "and other stuff\n"] 

请注意,openKernel模块的一种方法。

让我们确认一下:

puts IO.read(FName)
My name is Chris
My name is John
My name is Chris
and other stuff

1。 heredoc没有缩进。