Edit each line in a file in Ruby

女生的网名这么多〃 提交于 2019-11-28 21:24:26
Mike Lewis

The one of the better solutions(and safest) is to create a temporary file using TempFile, and move it to the original location(using FileUtils) once you are done:

   require 'fileutils'
   require 'tempfile'

    t_file = Tempfile.new('filename_temp.txt')
    File.open("filename.txt", 'r') do |f|
      f.each_line{|line| t_file.puts line.split(",")[0].to_s }
    end
    t_file.close
    FileUtils.mv(t_file.path, "filename.txt")

Another way to modify the file inplace is to use the -i switch

ruby -F"," -i.bak -ane 'puts $F[0]' file

File processing using code differs substantially from what we are doing when we, for example, edit the file in a text editor. File operations offered by operating systems are quite limited in that matter (due to numerous, partly historical reasons - think magnetic tapes).

In short, you should probably create another file and write data to it (Mike provided code for that), or load entire file in memory (which can be bad idea if your file is huge) and overwrite it with processed data.

Just for practice, here's how you could actually edit file in-place. As you can see, not the prettiest sight:

File.open('foo', 'r+') do |file|
  write_pos = 0
  file.each do |line|
    word = line.chomp.split(',').first
    read_pos = file.pos
    file.pos = write_pos
    file.puts word
    write_pos = file.pos
    file.pos = read_pos
  end
  file.truncate write_pos
end

I think you misunderstand what this line

file.each_line { |line| line = line.split(",")[0].to_s }

really does. It takes a line, splits it on a comma, takes the first value, turns it to a string (which it was already), assigns the result to the block-local variable 'line'. And then?
It goes on to the next line, and nothing is done with the previous one - it's all gone. See the other answers how to remedy this.

DavidG

The problem with the accepted answer is that it modifies file permissions and ownership (pay attention to that).

Another approach is to use inplace editing inside Ruby (not from the command line):

#!/usr/bin/ruby

def inplace_edit(file, bak, &block)
    old_stdout = $stdout
    argf = ARGF.clone

    argf.argv.replace [file]
    argf.inplace_mode = bak
    argf.each_line do |line|
        yield line
    end
    argf.close

    $stdout = old_stdout
end

inplace_edit 'test.txt', '.bak' do |line|
    line = line.gsub(/search1/,"replace1")
    line = line.gsub(/search2/,"replace2")
    print line unless line.match(/something/)
end

If you don't want to create a backup then change '.bak' to ''.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!