Reputation: 30886
I have a large file in a ruby variable, it follows a common pattern like so:
// ...
// comment
$myuser['bla'] = 'bla';
// comment
$myuser['bla2'] = 'bla2';
// ...
I am trying to given a 'key' replace the 'value'
This replaces the entire string how do I fix it? Another method I thought is to do it in two steps, step one would be to find the value within the quotes then to perform a string replace, what's best?
def keyvalr(content, key, value)
return content.gsub(/\$bla\[\'#{key}\'\]\s+\=\s+\'(.*)\'/) {|m| value }
end
Upvotes: 0
Views: 359
Reputation: 160551
I'd use something like:
text = %q{
// ...
// comment
$myuser['bla'] = 'bla';
// comment
$myuser['bla2'] = 'bla2';
// ...
}
from_to = {
'bla' => 'foo',
'bla2' => 'bar'
}
puts text.gsub(/\['([^']+)'\] = '([^']+)'/) { |t|
key, val = t.scan(/'([^']+)'/).flatten
"['%s'] = '%s'" % [ key, from_to[key] ]
}
Which outputs:
// ...
// comment
$myuser['bla'] = 'foo';
// comment
$myuser['bla2'] = 'bar';
// ...
This is how it works:
If I do:
puts text.gsub(/\['([^']+)'\] = '([^']+)'/) { |t|
puts t
}
I see:
['bla'] = 'bla'
['bla2'] = 'bla2'
Then I tried:
"['bla'] = 'bla'".scan(/'([^']+)'/).flatten
=> ["bla", "bla"]
That gave me a key, "value" pair, so I could use a hash to look-up the replacement value.
Sticking it inside a gsub
block meant whatever matched got replaced by my return value for the block, so I created a string to replace the "hit" and let gsub
do its "thang".
I'm not a big believer in using long regex. I've had to maintain too much code that tried to use complex patterns, and got something wrong, and failed to accomplish what was intended 100% of the time. They're very powerful, but maintenance of code is a lot harder/worse than developing it, so I try to keep patterns I write in spoon-size pieces, having mercy on those who follow me in maintaining the code.
Upvotes: 0
Reputation: 44259
The .*
is greedy and consumes as much as possible (everything until the very last '
). Make that .
a [^']
then it is impossible for it to go past the first closing '
.
/(\$bla\[\'#{key}\'\]\s+\=\s+\')[^']*(\')/
I also added parentheses to capture everything except for the value, which is to be replaced. The first set of parens will correspond to \1
and the second to \2
. So that you replace the match of this with:
"\1yournewvaluehere\2"
Upvotes: 1