Question

Say I have a file.txt that contains, among other things, a line that is Value=50. I don't know for sure the number of the line because the contents of the file may vary. At some point on my code, I want to change this line, replace it with, say, Value=30. I have a code for this already, but I can't figure out how to replace instead of adding another line.

My current code:

f = File.open('file.txt', 'r+')
f.any? do |line|
  if line.include?("Value")
    num = line.split('=').last
    newNum = 30
    line = line.gsub(/#{vol}/, newNum.to_s)
    f.write(line) 
  end
end
f.close

And the file.txt would be something like

foo
fooooo
Value=50
foo

It works great, but instead of replacing the old Value= line, it just adds a new one, sometimes in front and sometimes below it. I've already tried just leaving the line.gsub() part, but it made no changes to the file. I've tried f.puts(line) too, but if I remember correctly it would just add a new line.

I'm using this code in RPG Maker, so I'd like to solve this without libraries like Fileutils, unless they're extremely necessary.

Was it helpful?

Solution

Let's analyze what's going wrong here. File#any? returns true or false, according as its block returns true for at least one of the block arguments passed. You are not returning true or false from the block and you have no interest in the question of whether the result of File#any? is true or false. So this is clearly the wrong method.

Moreover, as you rightly say, you are writing a new (added) line, not in any way replacing the existing line.

What you want to do is cycle through the file line by line, reading each line, and:

  • If the line doesn't contain the target string, write the very same line

  • If the line does contain the target string, write the substituted line

Thus you will read the whole file and write the whole file (with or without the substitution) in its place. This approach actually involves two files, since you have already read the line before the time comes to write it.

Alternatively you could just read the whole file at once, split it into lines, look for the target and perform the substitution, join back into a single string, and write it. If the files are small (so that the strings are small), this is much the simplest way.

For the correct patterns, see https://stackoverflow.com/a/4399299/341994

OTHER TIPS

Because you are opening file with r+ mode you are effectively opening it for append. I would recommend you open a new file for output. Because you are not printing the existing lines, there is no way for them not to be there. You can only add the correct line after you find the line you want to change.

You could use gsub to replace that value:

text = File.read(file_name)
replace = text.gsub(/Value\=\d+/, "Value=#{newNum}")
File.open(filepath, "w") {|file| file.puts replace}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top