Jump to content

Recommended Posts

I've read DarkWater's Regex tutorial and I'm getting the hang of Regular Expressions. I've gotten this:

 

#^([\$]?)([0-9]*\.?[0-9]{0,2})$#

 

to test if the string represents a money value. However some people seperate thousands with commas and some with spaces. I want to add that but I'm not sure how to put that in.

Link to comment
https://forums.phpfreaks.com/topic/136384-regex-to-test-money-value/
Share on other sites

<?php
$strings[] = '$900.00';
$strings[] = '$900,001.00';
$strings[] = '$900 001.00';

foreach ($strings as $string)
preg_match('#^([\$]?)([0-9,\s]*\.?[0-9]{0,2})$#', $string, $matches[]);

print_r($matches);

die();
?>

 

Is that what you are looking for?

why the [\$] if its not a range of characters?

take a look at some patterns for example of the same value with your different formats

12345678.90

$12345678.90

$12,345,678.90

12 345 678.90

$12,345,678.9

 

Since these are all gonna be individual strings, And we are checking the whole string. we start with

^

to signify the start of the string

the $ is optional, regex has different designators,

  • no designator = just once
  • * = any number (0+)
  • + = one or more (1+)
  • ? = zero or one

in this instance we want ?, but ya was right ya have to escape the '$' as it has significance in a regex pattern so next set is

$?

now comes the tricky part, cuz ya not shure how many digits are gonna be involved or if a seperator will be used.

but we do know, the pattern of numbers usually looks like:

\d?\d?\d[ ,]?

if ya look at the designators above, we have optional digit optional digit and digit followed by either ' ' or a ','

but we need to repeat this cycle an unknown number of times, we can assign this as a capture group

and give the capture group a designator as well

(\d?\d?\d[ ,]?)*

btw did u notice we can assign all those \d's a designator as well? instead of looking each one individually, we can assign a range to the \d, since we know we will always have 1, to a max of 3. we use the range designator {min,max}

so now it looks like

(\d{1,3}[ ,]?)*

now to finish off our regex pattern with the cents, if its there, we can use the capture trick or do as u have done, lets go with the capture group to show the other way?

(\.\d{0,2})?

and of course, the last part, the end of string delimeter.

$

 

so know ya shud have a pretty complex regex, that can figure out the differences of the same value with different layouts

^\$?(\d{1,3}[ ,]?)*(\.\d{0,2})?$

 

I Believe that does it :)

 

I wasn't too far off. But here's the thing, "$90 0 001.00" passes too. I could do str_replace and remove spaces and commas.

or ya can expand on the regex to capture 3 digits after an initial 1-3 digit capture

^\$?\d{1,3}([ ,]?\d{3})*(\.\d{0,2})?$

I believe thats correct :)

 

 

I think my angle on this would be to simplify the initial array values (strip out any spaces, commas and dollar signs), check to see if what remains is representative in dollar format (only numbers with a single decimal and numbers (optional), then automatically add the dollar sign and commas in the appropriate places, like thus:

 

$str = array('$900.00', '$900,001.35', '900 001', '$6 75 8 3 1.2', '$1234.5');
foreach ($str as $val){
   $trans = array(' ' => '', ',' => '', '$' => ''); // replacement values from spaces, dollar signs & commas to nothingness
   $val = strtr($val, $trans); // execute those replacements if found
   preg_match('#^[0-9]+(\.[0-9]{0,2})?$#', $val, $matches);
   $matches[0] = '$' . number_format($matches[0], 2);
   echo $matches[0] . '<br />';
}

 

Output:

 

$900.00
$900,001.35
$900,001.00
$675,831.20
$1,234.50

Ok.. one hitch I didn't see coming is if an key in the initial $str array has letters entered by accident.. According to my snippet provided, the result in this case will be $0.00... so here is the revised code which solves this:

 

$str = array ('$900.00', '$900,001.35', '900 001', '$6 75 K 3 1.2', '$1234.5');
foreach ($str as $val){
   $trans = array(' ' => '', ',' => '', '$' => ''); // replacing spaces, dollar signs & commas with nothingness
   $val = strtr($val, $trans);
   if (preg_match('#^[0-9]+(\.[0-9]{0,2})?$#', $val, $matches)){
      $matches[0] = '$' . number_format($matches[0], 2);
      echo $matches[0] . '<br />';
   }
}

 

Output:

$900.00
$900,001.35
$900,001.00
$1,234.50

 

Note the '$6 75 K 3 1.2' entry in the $str array.. this entry will not be included in the final ouput, as it lacks only digits (with the optional decimal and digits).

 

 

Okay well if you're going to try and make a number out of arbitrary stuff being entered in at arbitrary places (random money formats, letters, whatever....), why not just make a really simple.  Just extract the numbers.  Who cares where they are or what was used. We'll throw in a decimal match, since there is a difference between 100.00 and 1.0000.  Then money_format it.

 

preg_match_all("/\d|\./",$string, $match);
setlocale(LC_MONETARY, 'en_US');
$num = money_format('%n', implode($match[0]));

 

@ Crayon Violent,

 

Touché, my friend :) This was made much more simplistic than my solution for sure.

One *potential* crux could depend, I suppose on how your php is configured? Is money_format a PECL extension or something?

 

When I tried your snippet on my local machine (running PHP 5.2.6), I got a "Fatal error: Call to undefined function money_format()" error...Therefore, I do not have this extension... but when I tested this online with my hosting service provider, it worked out nicely. So I guess "results may vary" so to speak.. but assuming if the hosting provider of the OP in question has this extension / configuration figured properly, it should work nicely.

@ Crayon Violent,

 

Touché, my friend :) This was made much more simplistic than my solution for sure.

One *potential* crux could depend, I suppose on how your php is configured? Is money_format a PECL extension or something?

 

When I tried your snippet on my local machine (running PHP 5.2.6), I got a "Fatal error: Call to undefined function money_format()" error...Therefore, I do not have this extension... but when I tested this online with my hosting service provider, it worked out nicely. So I guess "results may vary" so to speak.. but assuming if the hosting provider of the OP in question has this extension / configuration figured properly, it should work nicely.

 

money_format is not available in windows environment. On a Linux server it would work.

 

Look at number_format the user examples, one posted a money formater that may help you. There is also one that can be found on the money_format page.

money_format is not available in windows environment. On a Linux server it would work.

 

Ah, that would explain why I couldn't getting running locally (local is windows (2000 to boot :( ) ... host is Linux based.. so that also explains why it would work live).

I did make use of number_format in my previous example.. so I suppose, taking Crayon's idealogy and integrating it into my own, I come up with:

 

$str = array ('$900.00', '$900,001.35', '900 001', '$6 75 K 34gtJ 1.2', '$1234.5', 'hyg6789,42Jk.805.8');
foreach ($str as $val){
   preg_match_all('#[0-9.]#', $val, $matches);
   $matches = '$' . number_format(implode($matches[0]), 2);
   echo $matches . '<br />';
}

 

Output:

$900.00
$900,001.35
$900,001.00
$675,341.20
$1,234.50
$678,942.81

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.