Reputation: 17
Hi im trying to create a regex for currency. The part after the decimal works fine. However I am having problems with the first part. I want it to accept numbers such as:
00.12
0.12
00
0
But not numbers with leading zeros like:
0012.12
00023
This is what i have but i cannot get it to work
^([1-9][0-9]*|0|00)+(\.(\d){2})?$
Upvotes: 1
Views: 331
Reputation: 620
[Edited]
Now my answer fits what is really asked:
^(0{1,2}|([1-9][0-9]*))(?:\.[0-9]{2})?$
You can try this here: https://regex101.com/r/8KJhk3/5
Upvotes: 0
Reputation: 5224
You need to remove the quantifier +
on the first capture group -- it will permit multiple repetitions of 0
or 00
. In other words, 000
, 0000
, 00000
, etc. would be deemed valid as leading portions of the string. The grouping allows for any of the three types. So a regex such as
^(0{1,2}|[1-9]\d*)([.]\d\d)?$
will achieve your goal.
https://regex101.com/r/Tb1x6x/2/
Upvotes: 1
Reputation: 47900
You only need to check from the front of the string for 1 or more zeros that are followed by a 1 through 9 digit. This logic means that the required regex pattern can be kept very simple.
Code: (Demo)
$tests = [
'00.12',
'0.12',
'00',
'0',
'0012.12',
'00023',
];
foreach ($tests as $test) {
echo $test . (preg_match('~^0+[1-9]~', $test) ? ' fail' : ' pass') . "\n";
}
Output:
00.12 pass
0.12 pass
00 pass
0 pass
0012.12 fail
00023 fail
To correct your full pattern, you don't need the quantifier on your first group: (Demo)
echo preg_match('~^(?:[1-9]\d*|0{1,2})(?:\.\d{2})?$~', $test) ? ' pass' : ' fail'
But honestly, why not just cast them as floats instead of refusing values with leading zeros? (Demo) I would probably do that for a better user experience. Or maybe just standardize the input numbers with number_format()
. (Demo) Sounds perhaps like an XY problem here.
Upvotes: 1