19

I am searching for a RegEx for prices. So it should be X numbers in front, than a "," and at the end 2 numbers max.

Can someone support me and post it please?

PassionateDeveloper
  • 14,558
  • 34
  • 107
  • 176
  • There are currencies out there that need 3 decimal digits, even the USD and the EUR need 3 decimal digits in some scenarios. – Alix Axel Aug 11 '12 at 09:00
  • 1
    @AlixAxel When do USD and EUR need three digits after the comma? – Tim Apr 23 '13 at 08:26
  • 3
    @TimN: AFAIK, all EU countries must calculate the gas prices with a 3 digit precision. Another example: Forex exchange rates (5 decimal places I believe). – Alix Axel Apr 23 '13 at 08:43

14 Answers14

33

In what language are you going to use it?

It should be something like:

^\d+(,\d{1,2})?$

Explaination:

X number in front is: ^\d+ where ^ means the start of the string, \d means a digit and + means one or more

We use group () with a question mark, a ? means: match what is inside the group one or no times.

inside the group there is ,\d{1,2}, the , is the comma you wrote, \d is still a digit {1,2} means match the previous digit one or two times.

The final $ matches the end of the string.

Andrea Ambu
  • 38,188
  • 14
  • 54
  • 77
23

I was not satisfied with the previous answers. Here is my take on it:

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

|^^^^^^|^^^^^^^^^^^^^|^^^^^^^^^^^|
| 1-3  | 3 digits    | 2 digits  |
|digits| repeat any  |           |
|      | no. of      |           |
|      | times       |           |

(get a detailed explanation here: https://regex101.com/r/cG6iO8/1)

Covers all cases below

  • 5.00
  • 1,000
  • 1,000,000.99
  • 5,99 (european price)
  • 5.999,99 (european price)
  • 0.11
  • 0.00

But also weird stuff like

  • 5.000,000.00

In case you want to include 5 and 1000 (I personally wound not like to match ALL numbers), then just add a "?" like so:

\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?
elgehelge
  • 2,014
  • 1
  • 19
  • 24
10

I am working on similar problem. However i want only to match if a currency Symbol or String is also included in the String like EUR,€,USD or $. The Symbol may be trailing or leading. I don't care if there is space between the Number and the Currency substring. I based the Number matching on the previous discussion and used Price Number: \d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?

Here is final result:

(USD|EUR|€|\$)\s?(\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2}))|(\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?)\s?(USD|EUR|€|\$)

I use (\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?)\s?(USD|EUR|€|\$) as a pattern to match against a currency symbol (here with tolerance for a leading space). I think you can easily tweak it for any other currencies

A Gist with the latest Version can be found at https://gist.github.com/wischweh/b6c0ac878913cca8b1ba

r-hold
  • 941
  • 8
  • 30
  • 1
    almost perfect. As the comment above highlighted, this requires that any number larger than 3 digits have a comma to signal the thousands. So a value of "$9999.00" will not match but "$9,999.00" will match. I was able to get this working by changing that limit (USD|EUR|€|\$|£)\s?(\d{1,}(?:[.,]\d{3})*(?:[.,]\d{2}))|(\d{1,3}(?:[.,]\d{3})*(?:[.,]\d{2})?)\s?(USD|EUR) – Dan Hastings Jun 13 '18 at 11:48
  • I would rather use the following version as it allows for entries without decimal point to be matched too.. **(USD|EUR|€|\$|£)\s?(\d{1,}(?:[.,]*\d{3})*(?:[.,]*\d*))|(\d{1,3}(?:[.,]*\d*)*(?:[.,]*\d*)?)\s?(USD|EUR)** I.e. the original version would match only the second entry: - $2 - $2.54 - $34 but my version would match all – PepiX Mar 03 '22 at 11:33
4

So I ran into a similar problem, needing to validate if an arbitrary string is a price, but needed a lot more resilience than the regexes provided in this thread and many other threads.

I needed a regex that would match all of the following:

  • 5
  • 5.00
  • 1,000
  • 1,000,000.99
  • 5,99 (european price)
  • 5.999,99 (european price)
  • 0.11
  • 0.00

And not to match stuff like IP addresses. I couldn't figure out a single regex to deal with the european and non-european stuff in one fell swoop so I wrote a little bit of Ruby code to normalise prices:

if value =~ /^([1-9][0-9]{,2}(,[0-9]{3})*|[0-9]+)(\.[0-9]{1,9})?$/
  Float(value.delete(","))
elsif value =~ /^([1-9][0-9]{,2}(\.[0-9]{3})*|[0-9]+)(,[0-9]{1,9})?$/
  Float(value.delete(".").gsub(",", "."))
else
  false
end

The only difference between the two regexes is the swapped decimal place and comma. I'll try and break down what this is doing:

/^([1-9][0-9]{,2}(,[0-9]{3})*|[0-9]+)(\.[0-9]{1,9})?$/

The first part:

([1-9][0-9]{,2}(,[0-9]{3})*

This is a statement of numbers that follow this form: 1,000 1,000,000 100 12. But it does not allow leading zeroes. It's for the properly formatted numbers that have groups of 3 numerics separated by the thousands separator.

Second part:

[0-9]+

Just match any number 1 or more times. You could make this 0 or more times if you want to match: .11 .34 .00 etc.

The last part:

(\.[0-9]{1,9})?

This is the decimal place bit. Why up to 9 numerics, you ask? I've seen it happen. This regex is supposed to be able to handle any weird and wonderful price it sees and I've seen some retailers use up to 9 decimal places in prices. Usually all 0s, but we wouldn't want to miss out on the data ^_^

Hopefully this helps the next person to come along needing to process arbitrarily badly formatted price strings or either european or non-european format :)

Samwhoo
  • 312
  • 1
  • 8
3
^\d+,\d{1,2}$
Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
1
\d+((,\d+)+)?(.\d+)?(.\d+)?(,\d+)?

to cover all

  • 5

    5.00

    1,000

    1,000,000.99

    5,99 (european price)

    5.999,99 (european price)

    0.11

    0.00

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
1

I am currently working on a small function using regex to get price amount inside a String :

private static String getPrice(String input)
{
    String output = "";

    Pattern pattern = Pattern.compile("\\d{1,3}[,\\.]?(\\d{1,2})?");
    Matcher matcher = pattern.matcher(input);
    if (matcher.find())
    {
        output = matcher.group(0);
    }

    return output;
}

this seems to work with small price (0,00 to 999,99) and various currency :

$12.34 -> 12.34

$12,34 -> 12,34

$12.00 -> 12.00

$12 -> 12

12€ -> 12

12,11€ -> 12,11

12.999€ -> 12.99

12.9€ -> 12.9

£999.99€ -> 999.99

...

Tobliug
  • 2,992
  • 30
  • 28
1

Pretty simple for "," separated numbers(Or no seperation) with 2 decimal places , supports deliminator but does not force them. Needs some improvement but should work.

^((\d{1,3}|\s*){1})((\,\d{3}|\d)*)(\s*|\.(\d{2}))$

matches:
    1,123,456,789,134.45
    1123456134.45
    1234568979
    12,345.45
    123.45
    123
no match:
    1,2,3
    12.4
    1234,456.45

This may need some editing to make it function correctly

Quick explanation: Matches 1-3 numbers(Or nothing), matches a comma followed by 3 numbers as many times as needed(Or just numbers), matches a decimal point followed by 1 or 2 numbers(Or Nothing)

Scott Paterson
  • 392
  • 2
  • 17
0

This code worked for me !! (PHP)

preg_match_all('/\d+((,\d+)+)?(.\d+)?(.\d+)?(,\d+)?/',$price[1]->plaintext,$lPrices);
0

So far I tried, this is the best

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

https://regex101.com/r/xT8aQ7/1

Deviance
  • 465
  • 4
  • 9
0

This one reasonably works when you may or may not have decimal part but an amount shows up like this 100,000 - or 100,000.00. Tested using Clojure only

\d{1,3}(?:[.,]\\d{3})*(?:[.,]\d{2,3})
RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
0
r'(^\-?\d*\d+.?(\d{1,2})?$)'

This will allow digits with only one decimal and two digits after decimal

PM 77-1
  • 12,933
  • 21
  • 68
  • 111
0
^((\d+)((,\d+|\d+)*)(\s*|\.(\d{2}))$)

Matches:

1
11
111
1111111
11,2122
1222,21222
122.23
1223,3232.23

Not Matches:

11e
x111
111,111.090
1.000
Bruno Rohée
  • 3,436
  • 27
  • 32
Huda
  • 1
  • 2
-4

anything like \d+,\d{2} is wrong because the \d matches [0-9\.] i.e. 12.34,1.

should be: [0-9]+,[0-9]{2} (or [0-9]+,[0-9]{1,2} to allow only 1 decimal place)

anon
  • 1