Jump to content

[SOLVED] Matching a price.


play_

Recommended Posts

Hi.

 

Looking for a regular expression that would match a price. (without $).

 

So it would match:

  • 10
  • 10.99
  • 1,099
  • 1,099.49

 

So i guess the rule is, has to start with a number, has to end with a number, and can have one comma and/or one period in the middle

Link to comment
Share on other sites

~^([0-9]+(?:\.|,)?[0-9]+?$~

 

Of course, that pattern would fail if you encounter a value like 1,345,675.90 (since yours only allows a single comma or period).

 

My example:

setlocale(LC_CTYPE, 'C'); // ensure \d only matches 0-9
$price = array('10', '10.99', '1,099', '1,099.98', '1,34,5.68', '123.56.7', '3,454,579.9', '1,665.908');
foreach($price as $val){
    echo (preg_match('#^\d+(?:,\d{3})*(\.)?(?(1)\d{1,2})$#', $val))? $val . " is valid!<br />\n" : $val . " is NOT valid!<br />\n";
}

 

@play_, notice the final quantifying interval {1,2}... this would allow one or two digits after the decimal (if decimal is found). If you only want two digits after the decimal, simply change that interval to {2}

Link to comment
Share on other sites

Why not just ~^([0-9]{1,3})((,|\.)[0-9]{3,3})*?(\.[0-9]{1.2}$~

 

That way you have 1 - 3 numbers in the front, and then possible a comma or dot followed by three numbers, which is a repitive optional, with an option two decimal number at the end?

 

When I say why not, I'm not trying to one up you, I'm just trying to see if there's something wrong with my RegEx, I'm still kinda new at it

Link to comment
Share on other sites

Why not just ~^([0-9]{1,3})((,|\.)[0-9]{3,3})*?(\.[0-9]{1.2}$~

 

That way you have 1 - 3 numbers in the front, and then possible a comma or dot followed by three numbers, which is a repetitive optional, with an option two decimal number at the end?

 

When I say why not, I'm not trying to one up you, I'm just trying to see if there's something wrong with my RegEx, I'm still kinda new at it

 

There are a few issues with your pattern. It looks for a digit (1-3 times), followed by a comma or dot, followed by a digit, 3 times (I'll get to your additional errors in a second).. so if I stop right there, that could in itself match 3.543,678.432,788  see the problem? The cluster of 3 digits can alternate between commas and dots..

 

Additional issues with this pattern include the following..

 

((,|\.)[0-9]{3,3})*? Since you are using zero or more times, you don't need the ? to make it optional, as it is already optional (because it allows zero times)

 

Also, keep in mind that every set of parenthesis creates a capture.. since we are looking for a format, we don't care about doing specific captures.. so when you have something like (,|\.), this is getting stored into an internal variable.. when dealing with stuff we don't want to capture, we can resort to non-capture groups, which take on the format (?: .... ). In my pattern in my previous post, I make use of only 1 capture (the decimal), and if that decimal is there, then it must follow 1 or 2 digits. Earlier in my pattern, you'll notice (?:,\d{3})* which groups a comma followed by 3 digits, all of which is zero or more times.. but I don't care about storing this into an internal value.. so I use (?:,\d{3}) instead of (,\d{3}).

 

[0-9]{3,3} intervals like that {3,3} can simply be stated as {3}. When there is two values involved, the first is a minimum, the second a maximum.. so in this case, you are saying 3 minimum, 3 maximum.. by only stating a single value, this says, I want an x amount only (so {3} means look for something 3 consecutive times).

 

(\.[0-9]{1.2} there are two issues with this... a) there is no closing parenthesis.. b), your interval is using a dot instead of a comma to separate min and max values.

 

Link to comment
Share on other sites

Yeah, the setlocale was just incase.. (odds are, you won't have to deal with any additional stuff like exponents.. just a habit I have when dealing with short hand character classes), so it shouldn't be an issue without it. Sorry I botched my initial pattern... its 2:30am here.. Im tired.  :sleeping:

Link to comment
Share on other sites

Why not just ~^([0-9]{1,3})((,|\.)[0-9]{3,3})*?(\.[0-9]{1.2}$~

 

That way you have 1 - 3 numbers in the front, and then possible a comma or dot followed by three numbers, which is a repetitive optional, with an option two decimal number at the end?

 

When I say why not, I'm not trying to one up you, I'm just trying to see if there's something wrong with my RegEx, I'm still kinda new at it

 

There are a few issues with your pattern. It looks for a digit (1-3 times), followed by a comma or dot, followed by a digit, 3 times (I'll get to your additional errors in a second).. so if I stop right there, that could in itself match 3.543,678.432,788  see the problem? The cluster of 3 digits can alternate between commas and dots..

 

Additional issues with this pattern include the following..

 

((,|\.)[0-9]{3,3})*? Since you are using zero or more times, you don't need the ? to make it optional, as it is already optional (because it allows zero times)

 

Also, keep in mind that every set of parenthesis creates a capture.. since we are looking for a format, we don't care about doing specific captures.. so when you have something like (,|\.), this is getting stored into an internal variable.. when dealing with stuff we don't want to capture, we can resort to non-capture groups, which take on the format (?: .... ). In my pattern in my previous post, I make use of only 1 capture (the decimal), and if that decimal is there, then it must follow 1 or 2 digits. Earlier in my pattern, you'll notice (?:,\d{3})* which groups a comma followed by 3 digits, all of which is zero or more times.. but I don't care about storing this into an internal value.. so I use (?:,\d{3}) instead of (,\d{3}).

 

[0-9]{3,3} intervals like that {3,3} can simply be stated as {3}. When there is two values involved, the first is a minimum, the second a maximum.. so in this case, you are saying 3 minimum, 3 maximum.. by only stating a single value, this says, I want an x amount only (so {3} means look for something 3 consecutive times).

 

(\.[0-9]{1.2} there are two issues with this... a) there is no closing parenthesis.. b), your interval is using a dot instead of a comma to separate min and max values.

 

So how about

 

~^((?:[0-9]{1,3})(?:,[0-9]{3})*(?:\.[0-9]{1,2}))$~

 

Would that work? And as for capturing the data, he just said match, didn't he? Still, my above one should match the price as a number if I wrote it properly

Link to comment
Share on other sites

So how about

 

~^((?:[0-9]{1,3})(?:,[0-9]{3})*(?:\.[0-9]{1,2}))$~

 

Would that work? And as for capturing the data, he just said match, didn't he? Still, my above one should match the price as a number if I wrote it properly

 

Would it work? You could always try it yourself on an array of possible combinations of dollar figures (as I have done with my example).

It would almost work. The first and second groups work... (?:[0-9]{1,3})(?:,[0-9]{3})* but the last part - (?:\.[0-9]{1,2}) doesn't, because after the initial 3 digits in the number, whether the middle part exists or not [referring to (?:,[0-9]{3})*], the final part requires a decimal, followed by one or two digits. That last part could have the ? quantifier.

 

While you have done better with non capturing, you have encased the entire pattern in a capture (the very first and outer last parenthesis is not necessary). Also, you don't need to put a non capturing group on (?:[0-9]{1,3}) at the start, as this sequence is already required.. so one possible version based on yours could be (untested):

 

~^[0-9]{1,3}(?:,[0-9]{3})*(?:\.[0-9]{1,2})?$~

 

That way, after the first initial 3 digits, both second and last chunks are optional.

Link to comment
Share on other sites

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.