我有一个包含以下内容的文件:
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"但我真的不想这样做。
答案 0 :(得分:2)
你尝试做的事情是个坏主意。如果代码在中途崩溃,您的源/目标文件可能会损坏。
相反:
foreach
打开原始文件。遵循这些步骤有助于确保您的原始数据保持不变,直到最后的步骤#7和#8,然后将原始文件保存到备份并将新文件移动到旧文件中文件名。
Ruby使用foreach
的逐行IO比您尝试read
或readlines
更快,所以不要这样做。此外,read
和readlines
不具备可扩展性。如果原始文件很大,请考虑将其导入数据库,并使用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"]
请注意,open是Kernel
模块的一种方法。
让我们确认一下:
puts IO.read(FName)
My name is Chris
My name is John
My name is Chris
and other stuff
1。 heredoc没有缩进。