Regex currency amount
The reference Stack Overflow question's author has a very concrete problem, documented with their own list of test cases: their regex works on everything except negative amounts. A first answer (3 votes) fixes that and adds support for "USD$"... but actually testing that fix shows it accidentally drops support for a bare "$" sign, which worked in the original version - a real regression, never flagged in the thread. A widely republished pattern has a different flaw, found by testing it: its leading digit group before the first comma isn't limited to 3 characters, so "123456,789" passes as a valid thousands-separated amount. Here's a pattern that avoids both pitfalls, compared against the 3 real attempts.
/^(?:(?:USD)?\$)?-?(?:\d+|\d{1,3}(?:,\d{3})*)(?:\.\d{1,2})?$/passes 20/20 cases
Comparison of existing patterns
| Source | pattern | Score on the corpus | ReDoS |
|---|---|---|---|
| Stack Overflow — regex de l'auteur de la question, ne supporte ni les montants négatifs ni le préfixe USD$ (bug démontré avec son propre jeu de tests dans la question) | ^\$?(?:\d+|\d{1,3}(?:,\d{3})*)(?:\.\d{1,2}){0,1}$ | 16 / 20 | safe |
| Stack Overflow — réponse à 3 votes (MikeM), ajoute le négatif et USD$ mais supprime par erreur le support du symbole $ seul (régression trouvée en testant le motif) | ^(?:USD\$)?-?(?:\d+|\d{1,3}(?:,\d{3})*)(?:\.\d{1,2}){0,1}$ | 17 / 20 | safe |
| regexpattern.com — motif largement republié, groupe de tête non limité à 3 chiffres (accepte à tort « 123456,789 », trouvé en testant le motif) | ^-?\d+(,\d{3})*(\.\d{1,2})?$ | 15 / 20 | safe |
Implementation
const re = new RegExp("^(?:(?:USD)?\\$)?-?(?:\\d+|\\d{1,3}(?:,\\d{3})*)(?:\\.\\d{1,2})?$", "");
re.test(input);Limits
- L'ordre du signe négatif est figé : « $-123.45 » (symbole puis signe) est accepté, mais « -$123.45 » (signe puis symbole), pourtant une convention d'affichage tout aussi réelle, est rejeté par ce motif — un choix hérité de la structure de la réponse source, pas une règle universelle.
- N'accepte que le symbole « $ » (avec ou sans « USD » devant) : aucun autre symbole monétaire (€, £, ¥...) n'est reconnu, chacun nécessitant une adaptation du motif.
- Ne représente pas les montants négatifs entre parenthèses (« (123.45) »), une convention comptable réelle et répandue, distincte du simple signe moins.
- Valide uniquement la forme : n'arrondit rien, ne vérifie aucune plage de valeurs, et n'effectue aucune conversion — un montant syntaxiquement valide peut dépasser toute limite métier propre à l'application qui l'utilise.