Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace a line in a file using '+' File IO modes in Ruby

Tags:

file

file-io

ruby

Ruby beginner here!

I am aware that Ruby's File.open method has certain modes like r,w,a,r+,w+,a+ and the complimentary b. I totally understand the use of r,w and a modes. But I cannot seem to understand how to use the ones with the '+' symbol. Can anyone provide me with some links where there are examples as well as explanations for the use of it?

Can it be used to read a line and edit/replace it in place by a equal amount of content? If so, then how?

Sample data file: a.txt

aaa
bbb
ccc
ddd

Demo.rb

file = File.open "a.txt","r+"
file.each do |line|
  line = line.chomp
  if(line=="bbb")then
  file.puts "big"
  end
end
file.close

I am trying to replace "bbb" with "big" but I am getting this:- in notepad++

aaa
bbb
big

ddd

in notepad

aaa
bbb
bigddd
like image 807
Jazz Avatar asked Dec 20 '22 23:12

Jazz


1 Answers

snatched this documentation from another answer, so not mine, the solution is mine

r  Read-only mode. The file pointer is placed at the beginning of the file. This is the default mode. 
r+ Read-write mode. The file pointer will be at the beginning of the file. 
w  Write-only mode. Overwrites the file if the file exists. If the file does not exist, creates a new file for writing. 
w+ Read-write mode. Overwrites the existing file if the file exists. If the file does not exist, creates a new file for reading and writing.
a  Write-only mode. The file pointer is at the end of the file if the file exists. That is, the file is in the append mode. If the file does not exist, it creates a new file for writing. 
a+ Read and write mode. The file pointer is at the end of the file if the file exists. The file opens in the append mode. If the file does not exist, it creates a new file for reading and writing.

EDIT: here the solution to your sample, most of the time the whole string is gsubbed and written back to the file but 'infile' replacing without rewriting the whole file is also possible You should be cautious to replace with a string of the same length.

File.open('a.txt', 'r+') do |file|
  file.each_line do |line|
    if (line=~/bbb/)
      file.seek(-line.length-3, IO::SEEK_CUR)
      file.write 'big'
    end
  end
end 

=>
aaa
big
ccc
ddd

And this is a more conventional way, though more concise then most other solutions

File.open(filename = "a.txt", "r+") { |file| file << File.read(filename).gsub(/bbb/,"big") } 

EDIT2: i now realize this can still shorter

File.write(f = "a.txt", File.read(f).gsub(/bbb/,"big"))
like image 127
peter Avatar answered Dec 29 '22 10:12

peter