你可以寫在一個文件的中間,但你必須小心,以保持字符串的長度覆蓋相同,否則你會覆蓋下面的一些文本。我在這裏使用File.seek給出了一個例子,IO :: SEEK_CUR給出了文件指針的當前位置,在剛剛讀取的行的末尾,+1表示行末尾的CR字符。
look_for = "bbb"
replace_with = "xxxxx"
File.open(DATA, 'r+') do |file|
file.each_line do |line|
if (line[look_for])
file.seek(-(line.length + 1), IO::SEEK_CUR)
file.write line.gsub(look_for, replace_with)
end
end
end
__END__
aaabbb
bbbcccddd
dddeee
eee
執行後,在腳本結尾處,您現在有以下內容,而不是您想到的內容。
aaaxxxxx
bcccddd
dddeee
eee
考慮到這一點,使用這種技術的速度比經典的「讀取和寫入新文件」方法要好得多。 在音樂數據大小爲1.7 GB的文件上查看這些基準。 對於經典的方法,我使用了韋恩的技術。 基準測試是通過.bmbm方法完成的,因此文件的緩存功能沒有什麼大不了的。在Windows 7上使用MRI Ruby 2.3.0完成測試。 字符串被有效替換,我檢查了兩種方法。
require 'benchmark'
require 'tempfile'
require 'fileutils'
look_for = "Melissa Etheridge"
replace_with = "Malissa Etheridge"
very_big_file = 'D:\Documents\muziekinfo\all.txt'.gsub('\\','/')
def replace_with file_path, look_for, replace_with
File.open(file_path, 'r+') do |file|
file.each_line do |line|
if (line[look_for])
file.seek(-(line.length + 1), IO::SEEK_CUR)
file.write line.gsub(look_for, replace_with)
end
end
end
end
def replace_with_classic path, look_for, replace_with
temp_file = Tempfile.new('foo')
File.foreach(path) do |line|
if (line[look_for])
temp_file.write line.gsub(look_for, replace_with)
else
temp_file.write line
end
end
temp_file.close
FileUtils.mv(temp_file.path, path)
ensure
temp_file.close
temp_file.unlink
end
Benchmark.bmbm do |x|
x.report("adapt ") { 1.times {replace_with very_big_file, look_for, replace_with}}
x.report("restore ") { 1.times {replace_with very_big_file, replace_with, look_for}}
x.report("classic adapt ") { 1.times {replace_with_classic very_big_file, look_for, replace_with}}
x.report("classic restore") { 1.times {replace_with_classic very_big_file, replace_with, look_for}}
end
這給了
Rehearsal ---------------------------------------------------
adapt 6.989000 0.811000 7.800000 ( 7.800598)
restore 7.192000 0.562000 7.754000 ( 7.774481)
classic adapt 14.320000 9.438000 23.758000 (32.507433)
classic restore 14.259000 9.469000 23.728000 (34.128093)
----------------------------------------- total: 63.040000sec
user system total real
adapt 7.114000 0.718000 7.832000 ( 8.639864)
restore 6.942000 0.858000 7.800000 ( 8.117839)
classic adapt 14.430000 9.485000 23.915000 (32.195298)
classic restore 14.695000 9.360000 24.055000 (33.709054)
所以in_file中更換了快4倍。
如果您的代碼要讀取然後覆蓋會導致進程中途失敗,請考慮結果:您會冒着破壞文件的風險。 – 2010-12-10 00:29:49
好吧,作爲後續問題:從命令行,你可以這樣做:ruby -pe「gsub(/ blah /,'newstuff')」whatev.txt。這就是我想要做的,但我不想在命令行上這樣做,我想把它放在更大的東西里面。任何人都可以在內部告訴我,那個命令正在做什麼,從而給出了逐行編輯文件的錯覺?它是寫入臨時文件還是使用數組?因爲它似乎很快處理相當大的文件,而不是迄今爲止提供的建議。 – Hsiu 2010-12-10 08:42:08
這是一個很好的問題。你能把它變成一個新的問題嗎?這使得其他人更容易看到並回答它。另外,如果這個問題得到了您的滿意答覆,您能否接受該答案?謝謝! – 2010-12-16 23:20:58