replace lines in a file using hash key-value pairs

J

Johan Martinez

I want to replace matching lines in a file (config.ini) based on a hash
keys. The hash is returned by a yaml file here. Following is a code
snippet that I have written. For each key-value pair in hash I want to
go through all lines of a file and make string substitution for a
matching line. However, this code is not working and I noticed that
configfile.each method is executed only once. I appreciate any help on
what is wrong with this code.

<pre>

configfilename = "configuration.ini"
puts configfilename

# deployment properties object
depprops = DeployProperties.new("deploy.yaml")

# read config file
basedir = depprops.get_download["basedir"]

configfile = File.open("#{configfilename}","r+")

# read filelocations hash - for each key, replace with value
depprops.get_filelocations.each_pair do
|key,value|
puts " #{key} #{value}"
configfile.each do
|line|
puts line
# puts line if line.match("#{key}")
# line.sub!("/#{key}/","#{key} = #{value}")
end
end

</pre>

Also, is there any other way to implement search search-replace for all
matching lines in a files based on hash/yaml file.

Thanks
jM.
 
J

Johannes Held

Something like that?

hash = {"#HOST#" => "localhost", "#PORT#" => "2020" }
fdata = File.read("config.ini")
hash.each {|key, value| fdata.gsub(key, value) }
File.open("config_new.ini", "w") { |f| f.write(fdata) }
 
B

Brian Candler

Johan Martinez wrote in post #999809:
configfile = File.open("#{configfilename}","r+")

# read filelocations hash - for each key, replace with value
depprops.get_filelocations.each_pair do
|key,value|
puts " #{key} #{value}"
configfile.each do
|line|
puts line
# puts line if line.match("#{key}")
# line.sub!("/#{key}/","#{key} = #{value}")
end
end

These are nested loops. For the first key,value pair iteration,
configfile.each goes through each of the lines. After that the file is
exhausted, and .each won't do anything more. If you want to do that, you
have to either .rewind or open the file again:

depprops.get_filelocations.each_pair do |key,value|
File.open(configfilename) do |configfile|
configfile.each_line do |line|
...
end
end
end

Using the block form of File.open ensures that it's closed after each
iteration.

Of course, this is probably a very inefficient way to do what you want;
I'd rather iterate through the file once, and for each line do the
key/value substitutions. But then you get the results in a different
order, of course.
Also, is there any other way to implement search search-replace for all
matching lines in a files based on hash/yaml file.

Probably the most efficient way is to build a single regex that matches
all the substitutions in one go.

subs = {"hello"=>"goodbye", "world"=>"cruel life"}
keys = subs.keys.map { |k| Regexp.escape(k.to_s) }
pattern = Regexp.new("(?:#{keys.join("|")})")

lines = "hello world\ntesting\nhello again hello\n"
lines.each_line do |line|
puts line.gsub(pattern) { |k| subs[k] }
end
 
J

Johan Martinez

Thanks for the reply Johannes and Brian. Brian, I really appreciate for
explaining the problem with my code. Thanks again..

cheers,
jM.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top