5

This is what i've been using

\$?[0-9]+\.*[0-9]*

But when i was doing some testing i noticed that things like

$$$34.00 

would return as a match (but matcher.group()) just returns the matched substring. I don't want it to even pass the regular expression if the user enters more than one dollar sign so i tried this:

\${1}[0-9]+\.*[0-9]*

but this seems to behave the same as the regular expression i first typed. Right now i'm testing this in java but, i plan to use it in c++ using the Boost libraries. But Please don't give me that solution here because i'm trying to learn without someone giving me the answer.

But i do need help making it so the user can only enter one dollar sign (which is what i thought \${1} would do)

rage
  • 1,627
  • 3
  • 25
  • 35

6 Answers6

19

I would suggest avoiding the use of regular expressions for currency parsing, esp when Java provides you much simpler ways to solve this problem.

Consider this code:

String str = "$789.11"; // user entered value
Number number = null;
try {
    number = NumberFormat.getCurrencyInstance(Locale.US).parse(str);
} catch(ParseException pe) {
    // ignore
}

if (number != null) {
   // proceed as user entered a good value
}
else {
   // user didn't enter a good value
}
anubhava
  • 664,788
  • 59
  • 469
  • 547
  • 2
    shame I can't +1 this more times – sjr Jul 25 '13 at 18:37
  • 1
    This is pretty neat and i will definitely store it away in my toolbox but, I am trying to learn regular expressions so that was why i was trying to find a solution to this problem. – rage Jul 25 '13 at 18:46
  • Yes sure, its your prerogative. However just to let you know currency string can contain comma as well e.g. `$23,456.78` – anubhava Jul 25 '13 at 18:48
  • @rage: Check this answer for some pointers about using regex to parse US currency string: http://stackoverflow.com/questions/354044/what-is-the-best-u-s-currency-regex – anubhava Jul 25 '13 at 18:52
  • 1
    The `.parse(str)` method accepts incorrect strings like `$12asdf`. – Dean Schulze Dec 05 '17 at 19:20
  • I agree with Dean. I don't think the main response is +1. – ozn Oct 08 '18 at 05:58
12

Since you're doing this to learn regex...

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

Breakdown:

^\$ start of string with $ a single dollar sign

([1-9]\d{0,2}(,\d{3})*) 1-3 digits where the first digit is not a 0, followed by 0 or more occurrences of a comma with 3 digits

or

(([1-9]\d*)?\d) 1 or more digits where the first digit can be 0 only if it's the only digit

(\.\d\d)?$ with a period and 2 digits optionally at the end of the string

Matches:

$4,098.09
$4098.09
$0.35
$0
$380

Does not match:

$098.09
$0.9
$10,98.09
$10,980456
Syon
  • 6,625
  • 5
  • 33
  • 40
  • `(([1-9]\d*)?\d)` also takes care if the user does not enter commas doesn't it? I'm glad you posted this answer because i really learned alot from breaking up that regex myself and understanding it piece by piece – rage Jul 25 '13 at 19:56
  • Yes, that portion is specifically to capture when no commas are used in the string. – Syon Jul 25 '13 at 19:58
  • What is the opposite to get the $amount alone – Ashok kumar Ganesan May 27 '20 at 09:27
2

You can do something like [^\$]*\$? in the beginning. This would insure that there are no duplicate $ signs, but also matches if there is no $ present.

Also, if you are working with currency (possible decimal and 2 digits after), you should use [\.\d{2}]?.

This says that it can be a match if it's followed by ONE instance of a period and 2 digits or nothing at all. As stated in the comments, it can also match multiple periods in a row, so you shouldn't use the * quantifier after \.

Song Gao
  • 656
  • 4
  • 14
  • I didn't want to force the user into adding cents if he didn't need to. . would `\.{0,1}` work for that? – rage Jul 25 '13 at 18:10
  • `\.?` is the same as `\.{0,1}`.The `?` quantifier means it happens either once or not at all. You should also include the two possible cent digits after the period as I showed in my answer. Without them, `$27.50` would only match `$27.` – Song Gao Jul 25 '13 at 18:31
1

You are missing ^(beginning of string),$(end of string)

^\$\d+([.][0-9]+)?$
Anirudha
  • 30,881
  • 7
  • 64
  • 81
0

i know this is coming late but this seems to work for me

(\$)?[0-9]+\.*[0-9]*

i dont understand why it didnt work for you.

-1

[$](([1-9]+\.?\d*)|([0]\.\d*)|[0]) pattern ideally for this case.

This is standard Perl regex but could be use in JAVA with some libs.

Zaven Zareyan
  • 1,360
  • 8
  • 15