Ruby修改文件而不是创建新文件

Ruby修改文件而不是创建新文件,ruby,file,Ruby,File,假设我有以下Ruby代码,给定一个插入位置的散列,它读取一个文件并创建一个新文件,在这些位置插入额外的文本: insertpos = {14=>25,16=>25} File.open('file.old', 'r') do |oldfile| File.open('file.new', 'w') do |newfile| oldfile.each_with_index do |line,linenum| inserthere = in

假设我有以下Ruby代码,给定一个插入位置的散列,它读取一个文件并创建一个新文件,在这些位置插入额外的文本:

insertpos = {14=>25,16=>25}
File.open('file.old', 'r') do |oldfile|
    File.open('file.new', 'w') do |newfile|
        oldfile.each_with_index do |line,linenum|
            inserthere = insertpos[linenum]
            if(!inserthere.nil?)then
                line.insert(inserthere,"foo")
            end
            newfile.write(line)
        end
    end
end

现在,我想修改这个原始(旧)文件,而不是创建那个新文件。有人能给我一个如何修改代码的提示吗?谢谢

从根本上讲,在任何语言、任何操作系统上都很难做到这一点。将文件设想为磁盘上连续的字节序列(这是一个非常简单的场景,但它可以说明这一点)。您希望在文件的中间插入一些字节。你把那些字节放在哪里?没有地方放它们了!基本上,您必须将插入点“向下”后的现有字节“移位”为要插入的字节数。如果要在现有文件中插入多个节,则必须多次执行此操作!这将是非常缓慢的,如果出现错误,您将面临损坏数据的高风险

但是,您可以覆盖现有字节和/或附加到文件末尾。大多数Unix实用程序通过创建新文件并将其与旧文件交换来提供修改文件的外观。一些更复杂的方案,如数据库所使用的方案,允许在文件中间插入1。为此类操作保留空间(首次写入数据时),2。通过索引和其他技术允许文件中的非连续数据块,和/或3。写时复制方案,其中数据的新版本写入文件末尾,旧版本通过覆盖某种指示符而无效。对于您的简单用例,您很可能不想经历所有这些麻烦

无论如何,你已经找到了做你想做的事情的最好方法。您唯一缺少的是在最后一个
FileUtils.mv('file.new','file.old')
以新文件替换旧文件。如果我能进一步解释,请在评论中告诉我


(当然,您可以将整个文件读入内存,进行更改,并用更新的内容覆盖旧文件,但我不相信这就是您在这里要问的问题。)

这里有一些东西有望解决您的问题:

# 'source' param is a string, the entire source text
# 'lines' param is an array, a list of line numbers to insert after
# 'new' param is a string, the text to add
def insert(source, lines, new)
        results = []
        source.split("\n").each_with_index do |line, idx|
                if lines.include?(idx)
                        results << (line + new)
                else
                        results << line
                end
        end
        results.join("\n")
end

File.open("foo", "w") do |f|
        10.times do |i|
                f.write("#{i}\n")
        end
end

puts "initial text: \n\n"
txt = File.read("foo")
puts txt

puts "\n\n after inserting at lines 1,3, and 5: \n\n"
result = insert(txt, [1,3,5], "\nfoo")
puts result

如果这是一个相对简单的操作,您可以使用ruby one liner来完成,如下所示

ruby -i -lpe '$_.reverse!' thefile.txt

(例如在处找到)。

@santoshharma OP不想附加到文件中,他/她想在文件中间插入行。
ruby -i -lpe '$_.reverse!' thefile.txt