Tutorial :regular expressions to replace money pattern



Question:

I would like to ask for help with this, I wanted to check for a string matching a decimal followed by a letter (15M, 15.3M, 15T or 15.3T) and replace it with zeroes.

Like these: 15M -> 15000000 15.3M -> 15300000 15T -> 15000 15.3T -> 15300

I tried doing this with str_replace but can't get it right. Hope someone can help me.


Solution:1

"T" could be "thousand" or "trillion", you know.

$s = "15.7T";    $factors = Array('T' => 1000, 'M' => 1000000, 'B' => 1000000000.);    $matches = Array();  if (0 < preg_match('/([0-9]+(?:\.[0-9]*)?)([TMB])/', $s, $matches)) {      print("$s -> " . $matches[1] * $factors[$matches[2]]);  }  

prints:

15.7T -> 15700  

edit:

Anchoring (makes any garbage on the front or back mean no match):

'/^(...)$/'  

You may want to make whitespace allowed, however:

'/^\s*(...)\s*$/'  

You can also use "\d" in place of "[0-9]:

'/(\d+(?:\.\d*)?)([TMB])/'  

Case insensitivity:

'/.../i'  ...  print("$s -> " . $matches[1] * $factors[strtoupper($matches[2])]);  

Optional factor:

'/([0-9]+(?:\.[0-9]*)?)([TMB])?/'  $value = $matches[1];  $factor = isset($matches[2]) ? $factors[$matches[2]] : 1;  $output = $value * $factor;  

Use printf to control output formatting:

print($value) -> 1.57E+10  printf("%f", $value);  -> 15700000000.000000  printf("%.0f", $value);  -> 15700000000  

Stephan202 recommended a clever trick, put the "?" (optional) within the parens and you're guaranteed a match string, it just might be blank. Then you can use the blank as an array key to get the default value without having to test whether it matched or not.

Putting all that together:

$factors = Array('' => 1, 'T' => 1e3, 'M' => 1e6, 'B' => 1e9);  if (0 < preg_match('/^\s*(\d+(?:\.\d*)?)([TMB]?)\s*$/i', $s, $matches)) {      $value = $matches[1];      $factor = $factors[$matches[2]];      printf("'%s' -> %.0f", $s, $value * $factor);  }  


Solution:2

Alternative version which performs a conversion on all prices found:

  $multiply = array('' => 1, 'T' => 1000, 'M' => 1000000);      function convert($matches) {      global $multiply;      return $matches[1] * $multiply[$matches[3]];    }      $text = '15M 15.3M 15.3T 15';    print(preg_replace_callback('/(\d+(\.\d+)?)(\w?)/', 'convert', $text));  


Solution:3

In Perl:

#!/usr/bin/perl    use strict;  use warnings;    my %factors = (      B => 1_000_000_000,      M => 1_000_000,      T => 1_000,  );    while ( <DATA> ) {      next unless m{          ^          (?<number> -? [0-9]+ (?:\.[0-9]+)? )          (?<factor>B|M|T)?          $      }x;      my $number = $+{factor}                 ? sprintf( '%.0f', $+{number} * $factors{ $+{factor} } )                 : $+{number}                 ;      print $number, "\n";  }    __DATA__  15M  15B  15T  15.3M  15.3B  15.3T  15  15.3  

Output:

C:\Temp> z  15000000  15000000000  15000  15300000  15300000000  15300  15  15.3  


Solution:4

Have no idea how to make it in one regular expression, here is my try in Ruby.

#!/usr/bin/ruby    def trans s  h={"M"=>10**6 ,"T"=>10**3}  a = s.split(/[MT]/) + [s.split("").last]  (a[0].to_f * h[a[1]]).to_i  end      puts trans "15M"  puts trans "15.3M"  puts trans "15T"  puts trans "15.3T"  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »