Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read and overwrite text file simultaneously in Ruby

Tags:

ruby

I am trying to filter out duplicate lines in a text. I used ruby -i to edit in-place, but the result only outputs to stdout. So I tried to write by hand.

ARGV.each do |filename|
    File.open(filename, 'r+') do |file|
        ret = file.readlines.uniq.join()
        # file.rewind
        # file.truncate(???)
        # file.seek(0)
        # file.write ret
        file.puts ret
    end
end

None of them works. The best I can get is the content appended to the file, which merely makes more duplicates.

Please show some mercy to me.

like image 530
wolfrevo Avatar asked Apr 26 '26 21:04

wolfrevo


1 Answers

ARGV.each do |filename|
  new_content = File.readlines(filename).uniq(&:rstrip).join.rstrip
  File.write(filename, new_content)
end

This reads the entire file as individual lines, removes duplicate lines (ignoring the new line character(s)), concatenates the lines to create new file's content as one string and removes white spaces from its end. Finally we write new content to the file overriding existing content.

Note that the new version of the file won't have new line character at the end. If you want new line character at the end of the file you can just append it to new_content before the File::write call.


If you want to use the same handle for reading and writing, then do something like this:

ARGV.each do |filename|
  File.open(filename, 'r+') do |f|
    new_content = f.readlines.uniq(&:rstrip).join.rstrip  # Read the entire file as individual lines, removes duplicate lines (ignoring the new line character(s)), concatenate the lines to create new file's content as one string and remove white spaces from its end
    f.rewind                                              # Rewind to the beginning of the file
    f.write(new_content)                                  # Write new content to the file overriding existing content
    f.truncate(f.pos)                                     # Remove the file's content after the current position
  end
end

Although I can't see any real advantage of this version vs the first. The code becomes more messy, and we are forced to use File#truncate which is described as "Not available on all platforms.".

like image 153
TeWu Avatar answered Apr 29 '26 10:04

TeWu