ronnie
ronnie

Reputation: 17

Php Regex for currency, no leading zeros unless amount is 0 or 00

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

Answers (3)

[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

user3783243
user3783243

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

mickmackusa
mickmackusa

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

Related Questions