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.
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.".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With