clarkk
clarkk

Reputation: 27689

regexp monetary strings with decimals and thousands separator

https://www.tehplayground.com/KWmxySzbC9VoDvP9

Why is the first string matched?

$list = [
    '3928.3939392',     //  Should not be matched
    '4.239,99',
    '39',
    '3929',
    '2993.39',
    '393993.999'
];

foreach($list as $str){
    preg_match('/^(?<![\d.,])-?\d{1,3}(?:[,. ]?\d{3})*(?:[^.,%]|[.,]\d{1,2})-?(?![\d.,%]|(?: %))$/', $str, $matches);
    print_r($matches);
}

output

Array
(
    [0] => 3928.3939392
)
Array
(
    [0] => 4.239,99
)
Array
(
    [0] => 39
)
Array
(
    [0] => 3929
)
Array
(
    [0] => 2993.39
)
Array
(
)

Upvotes: 1

Views: 37

Answers (1)

Wiktor Stribiżew
Wiktor Stribiżew

Reputation: 626920

You seem to want to match the numbers as standalone strings, and thus, you do not need the lookarounds, you only need to use anchors.

You may use

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

See the regex demo

Details

  • ^ - start of string
  • -? - an optional -
  • (?: - start of a non-capturing alternation group:
    • \d{1,3}(?:[,. ]\d{3})* - 1 to 3 digits, followed with 0+ sequences of ,, . or space and then 3 digits
    • | - or
    • \d* - 0+ digits
  • ) - end of the group
  • (?:[.,]\d{1,2})? - an optional sequence of . or , followed with 1 or 2 digits
  • $ - end of string.

Upvotes: 2

Related Questions