web-dev-qa-db-fra.com

Quel est "le meilleur" RegEx de la devise américaine?

Une recherche rapide de l'expression rationnelle des devises donne beaucoup de résultats .

Le problème que j'ai en choisissant un de ces est que la regex est difficile à vérifier sans tester tous les cas Edge. Je pourrais passer beaucoup de temps là-dessus, comme des centaines d'autres développeurs l'ont déjà fait.

Quelqu'un a-t-il une expression régulière pour la devise américaine qui a été soigneusement testé

Ma seule exigence est que la chaîne correspondante soit U.S Currency et analyse System.Decimal

 [ws] [signe] [chiffres,] chiffres [. chiffres fractionnaires] [ws] 

 Les éléments entre crochets ([et]) sont facultatifs. 
 Le tableau suivant décrit chaque élément. 

 ELEMENT DESCRIPTION
ws espace blanc optionnel ... signe Un signe facultatif .
 Digits Séquence de chiffres allant de 0 à 9 .
, Symbole de séparation des milliers spécifique à la culture. 
. Un symbole de point décimal spécifique à la culture .
 Chiffres fractionnaires Une suite de chiffres allant de 0 à 9. 
44
Robert Claypool

voici quelques trucs des créateurs de Regex Buddy. Ceux-ci venaient de la bibliothèque, je suis convaincu qu'ils ont été minutieusement testés.

Nombre: Montant en devise (centimes obligatoires) Séparateurs facultatifs de milliers; fraction obligatoire à deux chiffres

Match; JGsoft:
^[+-]?[0-9]{1,3}(?:,?[0-9]{3})*\.[0-9]{2}$

Nombre: Montant en devise (cents en option) Séparateurs en milliers facultatifs; fraction facultative à deux chiffres

Match; JGsoft:
^[+-]?[0-9]{1,3}(?:,?[0-9]{3})*(?:\.[0-9]{2})?$

Nombre: Montant en devise US et EU (en cents facultatif) Peut utiliser les notations US-style 123,456,78 et européennes. Séparateurs facultatifs de milliers; fraction facultative à deux chiffres

Match; JGsoft:
^[+-]?[0-9]{1,3}(?:[0-9]*(?:[.,][0-9]{2})?|(?:,[0-9]{3})*(?:\.[0-9]{2})?|(?:\.[0-9]{3})*(?:,[0-9]{2})?)$
80
Keng

J'ai trouvé cette expression régulière en ligne sur www.RegExLib.com par Kirk Fuller, Gregg Durishan

Je l'utilise avec succès depuis deux ans.

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

Pas complètement testé du tout (je viens de l'écrire!), Mais semble se comporter correctement:

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

Ensemble d'essai:

0
1
33
555
4,656
4656
99,785
125,944
7,994,169
7994169
0.00
1.0
33.78795
555.12
4,656.489
99,785.01
125,944.100
-7,994,169
-7994169.23 // Borderline...

Wrong:
000
01
3,3
5.
555,
,656
99,78,5
1,25,944
--7,994,169
0.0,0
.10
33.787,95
4.656.489
99.785,01
1-125,944.1
-7,994E169

Remarque: Votre System.Decimal dépend des paramètres régionaux, difficile à créer dans une expression rationnelle, sauf peut-être lors de sa construction. J'ai supposé que les chiffres étaient regroupés par trois, même si, dans certaines cultures, il existe des règles différentes.
Il est trivial d'ajouter des espaces autour.

7
PhiLho

La réponse de Keng est parfaite, je veux juste ajouter que pour travailler avec 1 ou 2 décimales (pour la troisième version):

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

NET FIDDLE: https://dotnetfiddle.net/1mUpX2

3
MacGyver

Cette question date de quelques années et je voulais donc donner une réponse actualisée.

J'ai utilisé jQuery InputMask et cela fonctionne très bien pour le masquage des entrées/formats (tels que les numéros de téléphone, etc.), mais cela ne fonctionne PAS vraiment bien pour de l'argent, d'après mon expérience.

Pour la monnaie, je recommande fortement le plugin autoNumeric jQuery. Il est bien entretenu et ils ont essentiellement "pensé à tout" que je pourrais souhaiter comme monnaie.

J'utilise en fait une combinaison de ces deux plugins pour formater des numéros de téléphone, des formats de nombres (ISBN, etc.), ainsi que des devises (principalement la devise américaine).

Gardez à l'esprit que jquery.inputmask consiste principalement à contrôler le format d'une valeur, alors que autoNumeric consiste à contrôler spécifiquement le format de la devise.

1
Dan L

Au cas où vous voudriez que l'erreur humaine soit prise en compte, vous pourriez rendre le regex plus indulgent lorsque vous comparez les devises. J'ai utilisé la 2ème expression régulière de Nice de Keng et je l'ai rendue un peu plus robuste pour rendre compte de la faute de frappe.

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

Cela correspondra à n'importe lequel de ces chiffres de monnaie appropriés ou mutilés, mais ne récupérera pas le courrier indésirable à la fin de la zone:

$46,48382
$4,648,382
$ 4,648,382
$4,648,382.20
$4,648,382.2
$4,6483,82.20
$46,48382 70.25PD
$ 46,48382 70.25PD
0
jim

J'utilise l'expression régulière suivante pour la validation des devises:

^-?0*(?:\d+(?!,)(?:\.\d{1,2})?|(?:\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?))$

Vous pouvez également autoriser le signe dollar optionnel avancé:

^\$?-?0*(?:\d+(?!,)(?:\.\d{1,2})?|(?:\d{1,3}(?:,\d{3})*(?:\.\d{1,2})?))$

Vous pouvez facilement ajouter des tests pour les parenthèses au lieu de signer en ajoutant

\( and \)
0
eitanpo

Je regardais cela aussi et suis arrivé à la conclusion qu'il est préférable de construire la regex sur la base de la culture actuelle . Nous pouvons utiliser le 

CurrencyPositivePattern 
CurrencyGroupSeparator
CurrencyDecimalSeparator

propriétés de NumberFormatInfo pour obtenir le format requis.

Edit: quelque chose comme ça

NumberFormatInfo nfi = CultureInfo.CurrentCulture.NumberFormat;
      // Assign needed property values to variables.
      string currencySymbol = nfi.CurrencySymbol;
      bool symbolPrecedesIfPositive = nfi.CurrencyPositivePattern % 2 == 0;
      string groupSeparator = nfi.CurrencyGroupSeparator;
      string decimalSeparator = nfi.CurrencyDecimalSeparator;

      // Form regular expression pattern.
      string pattern = Regex.Escape( symbolPrecedesIfPositive ? currencySymbol : "") + 
                       @"\s*[-+]?" + "([0-9]{0,3}(" + groupSeparator + "[0-9]{3})*(" + 
                       Regex.Escape(decimalSeparator) + "[0-9]+)?)" + 
                       (! symbolPrecedesIfPositive ? currencySymbol : ""); 

référez-vous - http://msdn.Microsoft.com/en-us/library/hs600312.aspx

0
sidprasher

C'est ce que j'utilise:

Sans interlocuteur + ou -

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

Avec facultatif + ou -

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

net fiddle: https://jsfiddle.net/compsult/9of63cwk/12/

0
MIkee

En utilisant la réponse de Leandro, j'ai ajouté ^(?:[$]|) au début pour permettre le précédent signe dollar. 

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

Ce correspondant

136,402.99
25.27
0.33
$584.56
1
00.2
3,254,546.00
$3,254,546.00
00.01
-0.25
+0.85
+100,052.00

Ne correspond pas

11124.52
234223425.345
234.
.5234
a
a.23
32.a
a.a
z548,452.22
u66.36
0
henrywright88404

J'ai eu du succès avec cela (en prenant des morceaux de certaines des regex ci-dessus). Ne gère que des milliers, mais ne devrait pas être trop difficile d'étendre cela

case class CurrencyValue(dollars:Int,cents:Int)
def cents = """[\.\,]""".r ~> """\d{0,2}""".r ^^ {
  _.toInt
}
def dollarAmount: Parser[Int] = """[1-9]{1}[0-9]{0,2}""".r ~ opt( """[\.\,]""".r ~> """\d{3}""".r) ^^ {
  case x ~ Some(y) => x.toInt * 1000 + y.toInt
  case x ~ None => x.toInt
}
def usCurrencyParser = """(\$\s*)?""".r ~> dollarAmount ~ opt(cents) <~ opt( """(?i)dollars?""".r) ^^ {
  case d ~ Some(change) => CurrencyValue(d, change)
  case d ~ None => CurrencyValue(d, 0)
}
0
JoshMahowald