35

I need Help for currency regex in jQuery function.

  • It optionally allows "$" sign only one time in beginning.
  • It allows comma as digital-group-separator, but not in the beginning or the end.
  • It allows only 2 digits rounded after decimal point.
  • It allows only one decimal point and not in the beginning or the end.

Valid:

$1,530,602.24
1,530,602.24

Invalid:

$1,666.24$
,1,666,88,
1.6.66,6
.1555.

I tried /^\$?[0-9][0-9,]*[0-9]\.?[0-9]{0,2}$/i; it works fine except it matches 1,6,999.

Gary
  • 11,083
  • 14
  • 43
  • 68
user2205924
  • 441
  • 1
  • 4
  • 7
  • 4
    What do you have so far? What are the problems with it? – Wiseguy Apr 26 '13 at 17:56
  • I am new to jquery i do not know how to write regex function.If you can help me that would be great – user2205924 Apr 26 '13 at 18:00
  • 1
    your question has nothing to do with jQuery. In JavaScript, you have method `String.matches`, e.g. `var str="123.45"; if(str.matches(/YOUR_REGEX/)) alert("match"); else alert("not a match");` For concrete regular expressions see answers below. – Alex Shesterov Apr 26 '13 at 18:05
  • 1
    @Gary: thanks, was a typo. Unfortunately, I cannot edit the comment anymore. @user2205924: the method is called **`match`**, (not `matches`). Sorry. – Alex Shesterov Apr 26 '13 at 20:28
  • Possible duplicate of [What is "The Best" U.S. Currency RegEx?](http://stackoverflow.com/questions/354044/what-is-the-best-u-s-currency-regex) – Liam Jun 02 '16 at 14:51

2 Answers2

132

The RegEx

// Requires a decimal and commas
^\$?(([1-9]\d{0,2}(,\d{3})*)|0)?\.\d{1,2}$

// Allows a decimal, requires commas
(?=.*\d)^\$?(([1-9]\d{0,2}(,\d{3})*)|0)?(\.\d{1,2})?$

// Decimal and commas optional
(?=.*?\d)^\$?(([1-9]\d{0,2}(,\d{3})*)|\d+)?(\.\d{1,2})?$

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

// *Requires/allows X here also implies "used correctly"

The RegEx Breakdown

  • When the optional parts are too liberal, we need to look ahead and guarantee there's a number: (?=.*\d)
  • May or may not start with a dollar sign (I assume negatives are invalid): ^\$?
    • Follow that with -? to allow negative numbers
  • Begins with 1-3 numbers: [1-9]\d{0,2}
    • Could almost be (\d{1,3}), but that would allow "0,123"
    • One exception, can start with 0 in the case of "$0.50" or "0.50": |0
    • These regexes assume multiple leading 0's are invalid
  • Any number of three digit numbers separated by comma: (,\d{3})*
    • Remove ? before \. if you want to disallow numbers starting with "$."
  • Requires or allows decimal (one or two digits): \.\d{1,2} or (\.\d{1,2})? respectively
  • End with $ (unescaped) to make sure there's nothing after a valid number (like $1,000.00b)

To use the regex, use the string's match method and encase the regex between two forward slashes.

// The return will either be your match or null if not found
yourNumber.match(/(?=.)^\$?(([1-9][0-9]{0,2}(,[0-9]{3})*)|0)?(\.[0-9]{1,2})?$/);

// For just a true/false response
!!yourNumber.match(/(?=.)^\$?(([1-9][0-9]{0,2}(,[0-9]{3})*)|0)?(\.[0-9]{1,2})?$/);

Basic Usage Example

Demo with Test Cases

var tests = [
    "$1,530,602.24", "1,530,602.24", "$1,666.24$", ",1,666,88,", "1.6.66,6", ".1555."
];

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

for (i = 0; i < tests.length; i++) { 
  console.log(tests[i] + ' // ' + regex.test(tests[i]));
  document.write(tests[i] + ' // ' + regex.test(tests[i]) + '<br/>');
}
Gary
  • 11,083
  • 14
  • 43
  • 68
  • 2
    You should create a jsFiddle to prove it because this actually seems right – Ian Apr 26 '13 at 18:26
  • 6
    This is the best regex for this that I've seen to-date. Shame OP didn't mark as answer or comment why it's not accepted. You have my gratitude, regardless :) – user1020853 Jul 18 '14 at 12:37
  • I can't find the favorite flag for answers! Great response. – Eric L. Mar 17 '15 at 21:40
  • I tried removing the '$' proceeding '\.' in order to disallow the use of a dollar sign for "decimal and commas optional", but it still seems to be passing. Any thoughts? (?=.)^\$?(([1-9][0-9]{0,2}(,[0-9]{3})*)|[0-9]+)(\.[0-9]{1,2})?$ – Brian A Bird Jan 03 '17 at 22:19
  • The dollar sign was optional as well. Did you forget to remove the escape slash or '?' after it? `(?=.)^(([1-9][0-9]{0,2}(,[0-9]{3})*)|[0-9]+)?(\.[0-9]{1,2})?$` – Gary Jan 03 '17 at 22:36
  • Decimal/Commas optional case returns 1000 as invalid. – remarsh Apr 27 '18 at 23:28
  • Woops, I copied the wrong regex there on my last edit. Thanks for the heads up, it should be good now. – Gary Apr 28 '18 at 01:41
  • Effing wow. Perfect regex to solve this problem and a beautiful explaination to go with it! Super +rep Thanks legend – Allan W Smith Sep 07 '18 at 06:25
  • Hey @Gary, I'm using const CURRENCY = new RegExp(`(?=.*?\\d)^\\$?(([1-9]\\d{0,2}(,\\d{3})*)|\\d+)?(\\.\\d{1,2})?$`); which fails when a leading `$` is added? – Ben Racicot Feb 22 '19 at 13:20
  • 1
    @TR3B You double escaped the dollar sign. `^\\$` means a literal backslash, that must be at the beginning (^) and end ($) of your match... So, just that character. Remove one of the backslashes. – Gary Feb 22 '19 at 18:57
  • Thanks so much for replying but I don't understand. What should it look like? – Ben Racicot Feb 22 '19 at 20:09
  • I had some issues with this being a little too lenient in some cases (like leading zeros), and not accepting 4 digits after the decimal (which in accounting can be valid). This is my modification: (?=.*?[\d])^-?(([1-9]\d{0,2}(,\d{3})*)|0{1}|[1-9][0-9]+)?(\.\d{1,4})?$ – dmarra Jun 04 '19 at 17:55
  • @Gary what about no decimal, commas required? – TheRealFakeNews Mar 19 '20 at 17:29
  • @AlanH You could take the second example and remove the forward '?' from the first group, the '\.' group entirely, and the forward lookahead for the beginning (since now it's no longer at risk for being empty). Something like: `^\$?(([1-9]\d{0,2}(,\d{3})*)|0)?$` – Gary Mar 19 '20 at 18:58
  • `/(?=.*\d)^\$?(([1-9]\d{0,2}(,\d{3})*)|0)?(\.\d{2})?$/` is modified and workable for me... – Vishal Kumar Sahu Sep 22 '20 at 17:19
-1

Here is the regular expression that should achieve this for you.

The start must be numeric or $ sign. There can be any number of digits with commas, but it must start and end with a digit. There can optionally be a decimal point with up to two digits after it at the end of the line.

var your_input = "$1,000,000.00";
var valid_dollar_amt_regex = /^\$?[0-9][0-9,]*[0-9]\.?[0-9]{0,2}$/i;

if(valid_dollar_amt_regex.test(your_input))
    alert("Valid!");

Or use this function

function validate_money(i) {
    var valid_dollar_amt_regex = /^\$?[0-9][0-9,]*[0-9]\.?[0-9]{0,2}$/i;
    return valid_dollar_amt_regex.test(i);
}

See it working: http://jsfiddle.net/znuJf/

Brent
  • 304
  • 1
  • 7
  • it worked fine but it does not work for comma. for example ,120,0,00, – user2205924 Apr 26 '13 at 18:15
  • The fiddle satisfied all of your tests. ,120,0,00, False http://jsfiddle.net/znuJf/1/ – Brent Apr 26 '13 at 18:17
  • 2
    fiddle does not satisfy this test print_results("1,6,6677");if you can help for that would be great. Thank you so much. – user2205924 Apr 26 '13 at 19:51
  • 1
    It also passes `1,11,1111.00` because it just matches (several numbers + comma) and repeat indefinitely as long as it doesn't end with one. – Gary Apr 26 '13 at 20:54
  • 1
    I missed something else `[0-9][0-9,]*` means a number and and any number of numbers or commas, so `1,,,,1.00` also matches. Also, why is there a case-insensitive flag used for numbers? – Gary Apr 28 '13 at 03:44