[Solved] How to extract integer after “=” sign using ruby


I’d do something like this:

string = <<EOT
var i=0;
var recharge=[];
var recharge_text=[];
var recharge_String="";
var mrp="";
var talktime="";
var validity="";
var mode="";mrp='1100';
talktime="1200.00";
validity='NA';
mode="E-Recharge";
if(typeof String.prototype.trim !== 'function') {
String.prototype.trim = function() {
return this.replace(/^ +| +$/g, '');
}
}
mrp=mrp.trim();
if(isNaN(mrp))
{
recharge_text.push({MRP:mrp, Talktime:talktime, Validity:validity ,Mode:mode});
}
else
{
mrp=parseInt(mrp);
recharge.push({MRP:mrp, Talktime:talktime, Validity:validity ,Mode:mode});
}
mrp='2200';
talktime="2400.00";
EOT

hits = string.scan(/(?:mrp|talktime)='[\d.]+'/)
# => ["mrp='1100'", "talktime="1200.00"", "mrp='2200'", "talktime="2400.00""]

This gives us an array of hits using scan, where the pattern /(?:mrp|talktime)='[\d.]+'/ matched in the string. Figuring out how the pattern works is left as an exercise for the user, but Ruby’s Regexp documentation explains it all.

Cleaning that up to be a bit more useful:

hash = hits.map{ |s|
  str, val = s.split('=')
  [str, val.delete("'")]
}.each_with_object(Hash.new { |h, k| h[k] = [] }){ |(str, val), h| h[str] << val }

You also need to read about each_with_object and what’s happening with Hash.new as those are important concepts to learn in Ruby.

At this point, hash is a hash of arrays:

hash # => {"mrp"=>["1100", "2200"], "talktime"=>["1200.00", "2400.00"]}

You can easily extract a particular variable’s values, and can correlate them if need be.


what if i get a string instead of integer next to “=” sign?

string.scan(/(?:tariff)='[\p{Print}]+'/)

It’s important to understand what the pattern is doing. The regular expression engine has some gotchas that can drastically affect the speed of a search, so indiscriminately throwing in things without understanding what they do can be very costly.

When using (?:...), you’re creating a non-capturing group. When you only have one item you’re matching it’s not necessary, nor is it particularly desirable since it’s making the engine do more work. The only time I’d do that is when I need to refer back to what the capture was, but since you have only one possible thing it’ll match that becomes a moot-point. So, your pattern should be reduced to:

/tariff="[\p{Print}]+"/

Which, when used, results in:

%(tariff="abcdef abc a").scan(/tariff="[\p{Print}]+"/) 
# => ["tariff="abcdef abc a""]

If you want to capture all non-empty occurrences of the string being assigned, it’s easier than what you’re doing. I’d use something like:

%(tariff="abcdef abc a").scan(/tariff=".+"/) 
# => ["tariff="abcdef abc a""]

%(tariff="abcdef abc a").scan(/tariff="[^"]+'/) 
# => ["tariff="abcdef abc a""]

The second is more rigorous, and possible safer as it won’t be tricked by an line that has multiple single-quotes:

%(tariff="abcdef abc a", 'foo').scan(/tariff=".+"/) 
# => ["tariff="abcdef abc a", 'foo'"]

%(tariff="abcdef abc a", 'foo').scan(/tariff="[^"]+'/) 
# => ["tariff="abcdef abc a""]

Why that works is for you to figure out.

3

solved How to extract integer after “=” sign using ruby