Expression régulière pour faire correspondre les nombres avec ou sans virgules et décimales dans le texte

97

J'essaye de localiser et de remplacer tous les nombres dans un corps de texte. J'ai trouvé quelques exemples de regex, qui résolvent presque le problème, mais aucun n'est encore parfait. Le problème que j'ai est que les nombres dans mon texte peuvent ou non avoir des décimales et des virgules. Par exemple:

«Le renard de 5 000 lb a sauté par-dessus une clôture de 99 999 99998713 pieds.»

Le regex doit retourner " 5000" et " 99,999.99998713". Les exemples que j'ai trouvés séparent les nombres sur la virgule ou sont limités à deux décimales. Je commence à comprendre suffisamment les regex pour voir pourquoi certains exemples sont limités à deux décimales, mais je n'ai pas encore appris à le surmonter et à inclure également la virgule pour obtenir la séquence entière.

Voici ma dernière version:

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

Qui renvoie, " 5000", " 99,99", " 9.99" et " 998713" pour le texte ci-dessus.

Donut
la source
1
Quel langage de programmation ou quelle saveur regex?
Matt Ball
7
Il semble que presque toutes les réponses ici commettent l'erreur d'autoriser des choses comme .,.,.ou 9,9,9,9ou 9,9.99.9. Ces expressions régulières n'exigeront pas que les nombres soient au format approprié et, au pire, traiteront la ponctuation comme des nombres. Il y a quelques ajustements facultatifs possibles (par exemple s'il faut autoriser les zéros de début et de fin), mais certaines des réponses que je vois sont carrément incorrectes. Je n'aime vraiment pas le vote négatif, en particulier sur les tentatives honnêtes, mais je pense que les réponses doivent être nettoyées. C'est une question courante et sera certainement posée à nouveau.
Justin Morgan
Au cas où vous ne le sauriez pas, jetez un œil à regexpal.com
entonio
Désolé pour le retard Matt. J'utilise le code ActionScript 3. d'Adobe. Je pensais que le comportement de l'expression régulière était le même que celui de JavaScript, mais j'ai testé la suggestion de Justin sur regexpal.com et l' ai comparée aux résultats de mon application Flash et j'ai vu deux résultats différents à la fois faux.
Devrait fonctionner cette fois, sur la base de mes propres tests. Faites-moi savoir s'il a encore besoin d'être peaufiné.
Justin Morgan

Réponses:

289

EDIT: Étant donné que cela a suscité beaucoup de vues, permettez-moi de commencer par donner à tout le monde ce pour quoi ils ont cherché sur Google:

#ALL THESE REQUIRE THE WHOLE STRING TO BE A NUMBER
#For numbers embedded in sentences, see discussion below

#### NUMBERS AND DECIMALS ONLY ####
#No commas allowed
#Pass: (1000.0), (001), (.001)
#Fail: (1,000.0)
^\d*\.?\d+$

#No commas allowed
#Can't start with "."
#Pass: (0.01)
#Fail: (.01)
^(\d+\.)?\d+$

#### CURRENCY ####
#No commas allowed
#"$" optional
#Can't start with "."
#Either 0 or 2 decimal digits
#Pass: ($1000), (1.00), ($0.11)
#Fail: ($1.0), (1.), ($1.000), ($.11)
^\$?\d+(\.\d{2})?$

#### COMMA-GROUPED ####
#Commas required between powers of 1,000
#Can't start with "."
#Pass: (1,000,000), (0.001)
#Fail: (1000000), (1,00,00,00), (.001)
^\d{1,3}(,\d{3})*(\.\d+)?$

#Commas required
#Cannot be empty
#Pass: (1,000.100), (.001)
#Fail: (1000), ()
^(?=.)(\d{1,3}(,\d{3})*)?(\.\d+)?$

#Commas optional as long as they're consistent
#Can't start with "."
#Pass: (1,000,000), (1000000)
#Fail: (10000,000), (1,00,00)
^(\d+|\d{1,3}(,\d{3})*)(\.\d+)?$

#### LEADING AND TRAILING ZEROES ####
#No commas allowed
#Can't start with "."
#No leading zeroes in integer part
#Pass: (1.00), (0.00)
#Fail: (001)
^([1-9]\d*|0)(\.\d+)?$

#No commas allowed
#Can't start with "."
#No trailing zeroes in decimal part
#Pass: (1), (0.1)
#Fail: (1.00), (0.1000)
^\d+(\.\d*[1-9])?$

Maintenant que ce n'est plus le cas, la plupart des éléments suivants sont des commentaires sur la complexité des expressions rationnelles si vous essayez d'être intelligent avec elles, et pourquoi vous devriez chercher des alternatives. Lisez à vos risques et périls.


Ceci est une tâche très commune, mais toutes les réponses que je vois ici jusqu'à présent acceptera les entrées qui ne correspondent pas à votre format numérique, tels que ,111, 9,9,9ou même .,,.. C'est assez simple à corriger, même si les nombres sont incorporés dans un autre texte. À mon humble avis tout ce qui ne parvient pas à tirer 1,234.56 et 1234- et seuls les numéros -hors de abc22 1,234.56 9.9.9.9 def 1234est une mauvaise réponse.

Tout d'abord, si vous n'avez pas besoin de faire tout cela dans une seule regex, ne le faites pas. Une seule expression régulière pour deux formats de nombre différents est difficile à maintenir même s'ils ne sont pas incorporés dans un autre texte. Ce que vous devez vraiment faire est de diviser le tout sur des espaces, puis d'exécuter deux ou trois expressions rationnelles plus petites sur les résultats. Si ce n'est pas une option pour vous, continuez à lire.

Modèle de base

Compte tenu des exemples que vous avez donnés, voici une expression régulière simple qui autorise à peu près n'importe quel 0000format entier ou décimal et bloque tout le reste:

^\d*\.?\d+$

En voici un qui nécessite un 0,000format:

^\d{1,3}(,\d{3})*(\.\d+)?$

Mettez-les ensemble, et les virgules deviennent facultatives tant qu'elles sont cohérentes:

^(\d*\.?\d+|\d{1,3}(,\d{3})*(\.\d+)?)$

Numéros intégrés

Les modèles ci-dessus nécessitent que l'entrée entière soit un nombre. Vous recherchez des nombres incorporés dans du texte, vous devez donc desserrer cette partie. D'un autre côté, vous ne voulez pas qu'il voie catch22et pense qu'il a trouvé le numéro 22. Si vous utilisez quelque chose avec le support lookbehind (comme .NET), c'est assez simple: remplacez ^par (?<!\S)et $par (?!\S)et vous êtes bon aller:

(?<!\S)(\d*\.?\d+|\d{1,3}(,\d{3})*(\.\d+)?)(?!\S)

Si vous travaillez avec JavaScript ou Ruby ou quelque chose du genre, les choses commencent à paraître plus complexes:

(?:^|\s)(\d*\.?\d+|\d{1,3}(?:,\d{3})*(?:\.\d+)?)(?!\S)

Vous devrez utiliser des groupes de capture; Je ne peux pas penser à une alternative sans regarder derrière l'assistance. Les numéros que vous voulez seront dans le groupe 1 (en supposant que tout le match est le groupe 0).

Validation et règles plus complexes

Je pense que cela couvre votre question, donc si c'est tout ce dont vous avez besoin, arrêtez de lire maintenant. Si vous voulez devenir plus sophistiqué, les choses se compliquent très rapidement. Selon votre situation, vous souhaiterez peut-être bloquer tout ou partie des éléments suivants:

  • Entrée vide
  • Zéros non significatifs (par exemple, 000123)
  • Zéros de fin (par exemple 1.2340000)
  • Décimales commençant par la virgule décimale (par exemple .001 par opposition à 0,001)

Juste pour le plaisir, supposons que vous vouliez bloquer les 3 premiers, mais autorisez le dernier. Que devrais tu faire? Je vais vous dire ce que vous devez faire, vous devez utiliser une regex différente pour chaque règle et affiner progressivement vos correspondances. Mais pour relever le défi, voici comment faire tout cela en un seul modèle géant:

(?<!\S)(?=.)(0|([1-9](\d*|\d{0,2}(,\d{3})*)))?(\.\d*[1-9])?(?!\S)

Et voici ce que cela signifie:

(?<!\S) to (?!\S) #The whole match must be surrounded by either whitespace or line boundaries. So if you see something bogus like :;:9.:, ignore the 9.
(?=.)             #The whole thing can't be blank.

(                    #Rules for the integer part:
  0                  #1. The integer part could just be 0...
  |                  #
  [1-9]              #   ...otherwise, it can't have leading zeroes.
  (                  #
    \d*              #2. It could use no commas at all...
    |                #
    \d{0,2}(,\d{3})* #   ...or it could be comma-separated groups of 3 digits each.
  )                  # 
)?                   #3. Or there could be no integer part at all.

(       #Rules for the decimal part:
  \.    #1. It must start with a decimal point...
  \d*   #2. ...followed by a string of numeric digits only.
  [1-9] #3. It can't be just the decimal point, and it can't end in 0.
)?      #4. The whole decimal part is also optional. Remember, we checked at the beginning to make sure the whole thing wasn't blank.

Testé ici: http://rextester.com/YPG96786

Cela permettra des choses comme:

100,000
999.999
90.0009
1,000,023.999
0.111
.111
0

Cela bloquera des choses comme:

1,1,1.111
000,001.111
999.
0.
111.110000
1.1.1.111
9.909,888

Il y a plusieurs façons de rendre cette expression régulière plus simple et plus courte, mais comprenez que changer le modèle détendra ce qu'il considère comme un nombre.

Étant donné que de nombreux moteurs de regex (par exemple JavaScript et Ruby) ne prennent pas en charge la recherche négative, la seule façon de le faire correctement est d'utiliser des groupes de capture:

(:?^|\s)(?=.)((?:0|(?:[1-9](?:\d*|\d{0,2}(?:,\d{3})*)))?(?:\.\d*[1-9])?)(?!\S)

Les numéros que vous recherchez seront dans le groupe de capture 1.

Testé ici: http://rubular.com/r/3HCSkndzhT

Une dernière note

De toute évidence, c'est une regex massive, compliquée et presque illisible. J'ai apprécié le défi, mais vous devriez vous demander si vous voulez vraiment l'utiliser dans un environnement de production. Au lieu d'essayer de tout faire en une seule étape, vous pouvez le faire en deux: une expression régulière pour attraper tout ce qui pourrait être un nombre, puis une autre pour éliminer tout ce qui n'est pas un nombre. Ou vous pouvez effectuer un traitement de base, puis utiliser les fonctions d'analyse numérique intégrées de votre langage. Votre choix.

Justin Morgan
la source
1
C'est une très bonne tentative, mais il peut y avoir un problème - en fonction de la gourmandise du moteur, un nombre donné peut partiellement correspondre à deux des formats concurrents, au lieu de faire correspondre le bon - c'est-à-dire que 5000 peut donner 500 plus 0 Cela me rend un peu sceptique d'essayer de couvrir trop avec une seule expression, et c'est pourquoi j'ai donné une réponse plus simple avec la mise en garde d'éventuels faux positifs. En fin de compte, la rigueur des exigences devrait dicter la solution.
entonio
@entonio - C'est un bon point. Cela pourrait fonctionner avec la dernière modification. BTW, votre vote négatif ne venait pas de moi, puisque vous avez souligné le match potentiel 1,11,11.
Justin Morgan
J'utilise ActionScript, qui, je crois, se comporte de la même manière que JavaScript. En utilisant le premier modèle que vous avez recommandé, j'obtiens les résultats suivants sur ma chaîne de test (Pour validation, je renvoie simplement les correspondances enveloppées dans "<< [result] >>"): Le renard << 5 >> 000 lb. a sauté par-dessus une clôture << 9 >> 9 <<, 9 >> <<99>> <<. 9 >> <<99>> <<98>> <<71>> 3 pieds de clôture.
2
Eh bien, l'un de vos votes positifs vient de moi :) car je pense que votre réponse est aussi complète que possible et que vous y mettez du travail. Juste pour en faire un commentaire de contenu, une note à l'OP, le?: Au début des groupes est là pour qu'ils ne soient pas retournés de manière autonome dans le résultat ('capturé'), même s'ils contribuent à la mise en correspondance de l'expression entière; chaque nombre formaté dans l'entrée correspond à l'expression entière.
entonio
@Michael et @entonio - Voir la dernière modification, qui semble fonctionner. C'est l'un de ces problèmes de regex qui sont plus difficiles qu'il n'y paraît.
Justin Morgan
10

Il y a quelques jours, j'ai travaillé sur le problème de la suppression des zéros de fin de la chaîne d'un nombre .

Dans la continuité de ce problème, je trouve celui-ci intéressant car il élargit le problème aux nombres comportant des virgules.

J'ai pris le modèle de regex que j'avais écrit dans ce problème précédent sur lequel j'ai travaillé et je l'ai amélioré afin qu'il puisse traiter les nombres avec des virgules comme une réponse à ce problème.

J'ai été emporté par mon enthousiasme et mon goût pour les expressions régulières. Je ne sais pas si le résultat correspond exactement au besoin exprimé par Michael Prescott. Je serais intéressé de connaître les points qui sont en excès ou en manque dans mon regex, et de le corriger pour le rendre plus approprié pour vous.

Maintenant, après une longue session de travail sur cette regex, j'ai une sorte de poids dans le cerveau, donc je ne suis pas assez frais pour donner beaucoup d'explications. Si les points sont obscurs et si quelqu'un peut être suffisamment intéressé, n'hésitez pas à me le demander.

La regex est construite de manière à pouvoir détecter les nombres exprimés en notation scientifique 2E10 ou même 5,22,454.12E-00.0478 , supprimant également les zéros inutiles dans les deux parties de ces nombres. Si un exposant est égal à zéro, le nombre est modifié pour qu'il n'y ait plus d'exposant.

J'ai mis un peu de vérification dans le modèle pour que certains cas particuliers ne correspondent pas, par exemple « 12 ..57» ne correspond pas. Mais dans ', 111' la chaîne '111' correspond parce que la virgule précédente est considérée comme une virgule non pas dans un nombre mais une virgule de phrase.

Je pense que la gestion des virgules devrait être améliorée, car il me semble qu'il n'y a que 2 chiffres entre les virgules dans la numérotation indienne. Ce ne sera pas difficile à corriger, je présume

Voici un code illustrant le fonctionnement de mon regex. Il y a deux fonctions, selon que l'on veut que les nombres '.1245' soient transformés en '0.1245' ou non. Je ne serais pas surpris si des erreurs ou des correspondances ou des non-concordances indésirables subsisteraient pour certains cas de chaînes de nombres; alors j'aimerais connaître ces cas pour comprendre et corriger la carence.

Je m'excuse pour ce code écrit en Python, mais les regex sont trans-langage et je pense que tout le monde sera capable de comprendre le modèle du reex

import re

regx = re.compile('(?<![\d.])(?!\.\.)(?<![\d.][eE][+-])(?<![\d.][eE])(?<!\d[.,])'
                  '' #---------------------------------
                  '([+-]?)'
                  '(?![\d,]*?\.[\d,]*?\.[\d,]*?)'
                  '(?:0|,(?=0)|(?<!\d),)*'
                  '(?:'
                  '((?:\d(?!\.[1-9])|,(?=\d))+)[.,]?'
                  '|\.(0)'
                  '|((?<!\.)\.\d+?)'
                  '|([\d,]+\.\d+?))'
                  '0*'
                  '' #---------------------------------
                  '(?:'
                  '([eE][+-]?)(?:0|,(?=0))*'
                  '(?:'
                  '(?!0+(?=\D|\Z))((?:\d(?!\.[1-9])|,(?=\d))+)[.,]?'
                  '|((?<!\.)\.(?!0+(?=\D|\Z))\d+?)'
                  '|([\d,]+\.(?!0+(?=\D|\Z))\d+?))'
                  '0*'
                  ')?'
                  '' #---------------------------------
                  '(?![.,]?\d)')


def dzs_numbs(x,regx = regx): # ds = detect and zeros-shave
    if not regx.findall(x):
        yield ('No match,', 'No catched string,', 'No groups.')
    for mat in regx.finditer(x):
        yield (mat.group(), ''.join(mat.groups('')), mat.groups(''))

def dzs_numbs2(x,regx = regx): # ds = detect and zeros-shave
    if not regx.findall(x):
        yield ('No match,', 'No catched string,', 'No groups.')
    for mat in regx.finditer(x):
        yield (mat.group(),
               ''.join(('0' if n.startswith('.') else '')+n for n in mat.groups('')),
               mat.groups(''))

NS = ['  23456000and23456000. or23456000.000  00023456000 s000023456000.  000023456000.000 ',
      'arf 10000 sea10000.+10000.000  00010000-00010000. kant00010000.000 ',
      '  24:  24,  24.   24.000  24.000,   00024r 00024. blue 00024.000  ',
      '  8zoom8.  8.000  0008  0008. and0008.000  ',
      '  0   00000M0. = 000.  0.0  0.000    000.0   000.000   .000000   .0   ',
      '  .0000023456    .0000023456000   '
      '  .0005872    .0005872000   .00503   .00503000   ',
      '  .068    .0680000   .8   .8000  .123456123456    .123456123456000    ',
      '  .657   .657000   .45    .4500000   .7    .70000  0.0000023230000   000.0000023230000   ',
      '  0.0081000    0000.0081000  0.059000   0000.059000     ',
      '  0.78987400000 snow  00000.78987400000  0.4400000   00000.4400000   ',
      '  -0.5000  -0000.5000   0.90   000.90   0.7   000.7   ',
      '  2.6    00002.6   00002.60000  4.71   0004.71    0004.7100   ',
      '  23.49   00023.49   00023.490000  103.45   0000103.45   0000103.45000    ',
      '  10003.45067   000010003.45067   000010003.4506700 ',
      '  +15000.0012   +000015000.0012   +000015000.0012000    ',
      '  78000.89   000078000.89   000078000.89000    ',
      '  .0457e10   .0457000e10   00000.0457000e10  ',
      '   258e8   2580000e4   0000000002580000e4   ',
      '  0.782e10   0000.782e10   0000.7820000e10  ',
      '  1.23E2   0001.23E2  0001.2300000E2   ',
      '  432e-102  0000432e-102   004320000e-106   ',
      '  1.46e10and0001.46e10  0001.4600000e10   ',
      '  1.077e-300  0001.077e-300  0001.077000e-300   ',
      '  1.069e10   0001.069e10   0001.069000e10   ',
      '  105040.03e10  000105040.03e10  105040.0300e10    ',
      '  +286E000024.487900  -78.4500e.14500   .0140E789.  ',
      '  081,12.40E07,95.0120     0045,78,123.03500e-0.00  ',
      '  0096,78,473.0380e-0.    0008,78,373.066000E0.    0004512300.E0000  ',
      '  ..18000  25..00 36...77   2..8  ',
      '  3.8..9    .12500.     12.51.400  ',
      '  00099,111.8713000   -0012,45,83,987.26+0.000,099,88,44.or00,00,00.00must',
      '  00099,44,and   0000,099,88,44.bom',
      '00,000,00.587000  77,98,23,45.,  this,that ',
      '  ,111  145.20  +9,9,9  0012800  .,,.  1  100,000 ',
      '1,1,1.111  000,001.111   -999.  0.  111.110000  1.1.1.111  9.909,888']


for ch in NS:
    print 'string: '+repr(ch)
    for strmatch, modified, the_groups in dzs_numbs2(ch):
        print strmatch.rjust(20),'',modified,'',the_groups
    print

résultat

string: '  23456000and23456000. or23456000.000  00023456000 s000023456000.  000023456000.000 '
            23456000  23456000  ('', '23456000', '', '', '', '', '', '', '')
           23456000.  23456000  ('', '23456000', '', '', '', '', '', '', '')
        23456000.000  23456000  ('', '23456000', '', '', '', '', '', '', '')
         00023456000  23456000  ('', '23456000', '', '', '', '', '', '', '')
       000023456000.  23456000  ('', '23456000', '', '', '', '', '', '', '')
    000023456000.000  23456000  ('', '23456000', '', '', '', '', '', '', '')

string: 'arf 10000 sea10000.+10000.000  00010000-00010000. kant00010000.000 '
               10000  10000  ('', '10000', '', '', '', '', '', '', '')
              10000.  10000  ('', '10000', '', '', '', '', '', '', '')
           10000.000  10000  ('', '10000', '', '', '', '', '', '', '')
            00010000  10000  ('', '10000', '', '', '', '', '', '', '')
           00010000.  10000  ('', '10000', '', '', '', '', '', '', '')
        00010000.000  10000  ('', '10000', '', '', '', '', '', '', '')

string: '  24:  24,  24.   24.000  24.000,   00024r 00024. blue 00024.000  '
                  24  24  ('', '24', '', '', '', '', '', '', '')
                 24,  24  ('', '24', '', '', '', '', '', '', '')
                 24.  24  ('', '24', '', '', '', '', '', '', '')
              24.000  24  ('', '24', '', '', '', '', '', '', '')
              24.000  24  ('', '24', '', '', '', '', '', '', '')
               00024  24  ('', '24', '', '', '', '', '', '', '')
              00024.  24  ('', '24', '', '', '', '', '', '', '')
           00024.000  24  ('', '24', '', '', '', '', '', '', '')

string: '  8zoom8.  8.000  0008  0008. and0008.000  '
                   8  8  ('', '8', '', '', '', '', '', '', '')
                  8.  8  ('', '8', '', '', '', '', '', '', '')
               8.000  8  ('', '8', '', '', '', '', '', '', '')
                0008  8  ('', '8', '', '', '', '', '', '', '')
               0008.  8  ('', '8', '', '', '', '', '', '', '')
            0008.000  8  ('', '8', '', '', '', '', '', '', '')

string: '  0   00000M0. = 000.  0.0  0.000    000.0   000.000   .000000   .0   '
                   0  0  ('', '0', '', '', '', '', '', '', '')
               00000  0  ('', '0', '', '', '', '', '', '', '')
                  0.  0  ('', '0', '', '', '', '', '', '', '')
                000.  0  ('', '0', '', '', '', '', '', '', '')
                 0.0  0  ('', '', '0', '', '', '', '', '', '')
               0.000  0  ('', '', '0', '', '', '', '', '', '')
               000.0  0  ('', '', '0', '', '', '', '', '', '')
             000.000  0  ('', '', '0', '', '', '', '', '', '')
             .000000  0  ('', '', '0', '', '', '', '', '', '')
                  .0  0  ('', '', '0', '', '', '', '', '', '')

string: '  .0000023456    .0000023456000     .0005872    .0005872000   .00503   .00503000   '
         .0000023456  0.0000023456  ('', '', '', '.0000023456', '', '', '', '', '')
      .0000023456000  0.0000023456  ('', '', '', '.0000023456', '', '', '', '', '')
            .0005872  0.0005872  ('', '', '', '.0005872', '', '', '', '', '')
         .0005872000  0.0005872  ('', '', '', '.0005872', '', '', '', '', '')
              .00503  0.00503  ('', '', '', '.00503', '', '', '', '', '')
           .00503000  0.00503  ('', '', '', '.00503', '', '', '', '', '')

string: '  .068    .0680000   .8   .8000  .123456123456    .123456123456000    '
                .068  0.068  ('', '', '', '.068', '', '', '', '', '')
            .0680000  0.068  ('', '', '', '.068', '', '', '', '', '')
                  .8  0.8  ('', '', '', '.8', '', '', '', '', '')
               .8000  0.8  ('', '', '', '.8', '', '', '', '', '')
       .123456123456  0.123456123456  ('', '', '', '.123456123456', '', '', '', '', '')
    .123456123456000  0.123456123456  ('', '', '', '.123456123456', '', '', '', '', '')

string: '  .657   .657000   .45    .4500000   .7    .70000  0.0000023230000   000.0000023230000   '
                .657  0.657  ('', '', '', '.657', '', '', '', '', '')
             .657000  0.657  ('', '', '', '.657', '', '', '', '', '')
                 .45  0.45  ('', '', '', '.45', '', '', '', '', '')
            .4500000  0.45  ('', '', '', '.45', '', '', '', '', '')
                  .7  0.7  ('', '', '', '.7', '', '', '', '', '')
              .70000  0.7  ('', '', '', '.7', '', '', '', '', '')
     0.0000023230000  0.000002323  ('', '', '', '.000002323', '', '', '', '', '')
   000.0000023230000  0.000002323  ('', '', '', '.000002323', '', '', '', '', '')

string: '  0.0081000    0000.0081000  0.059000   0000.059000     '
           0.0081000  0.0081  ('', '', '', '.0081', '', '', '', '', '')
        0000.0081000  0.0081  ('', '', '', '.0081', '', '', '', '', '')
            0.059000  0.059  ('', '', '', '.059', '', '', '', '', '')
         0000.059000  0.059  ('', '', '', '.059', '', '', '', '', '')

string: '  0.78987400000 snow  00000.78987400000  0.4400000   00000.4400000   '
       0.78987400000  0.789874  ('', '', '', '.789874', '', '', '', '', '')
   00000.78987400000  0.789874  ('', '', '', '.789874', '', '', '', '', '')
           0.4400000  0.44  ('', '', '', '.44', '', '', '', '', '')
       00000.4400000  0.44  ('', '', '', '.44', '', '', '', '', '')

string: '  -0.5000  -0000.5000   0.90   000.90   0.7   000.7   '
             -0.5000  -0.5  ('-', '', '', '.5', '', '', '', '', '')
          -0000.5000  -0.5  ('-', '', '', '.5', '', '', '', '', '')
                0.90  0.9  ('', '', '', '.9', '', '', '', '', '')
              000.90  0.9  ('', '', '', '.9', '', '', '', '', '')
                 0.7  0.7  ('', '', '', '.7', '', '', '', '', '')
               000.7  0.7  ('', '', '', '.7', '', '', '', '', '')

string: '  2.6    00002.6   00002.60000  4.71   0004.71    0004.7100   '
                 2.6  2.6  ('', '', '', '', '2.6', '', '', '', '')
             00002.6  2.6  ('', '', '', '', '2.6', '', '', '', '')
         00002.60000  2.6  ('', '', '', '', '2.6', '', '', '', '')
                4.71  4.71  ('', '', '', '', '4.71', '', '', '', '')
             0004.71  4.71  ('', '', '', '', '4.71', '', '', '', '')
           0004.7100  4.71  ('', '', '', '', '4.71', '', '', '', '')

string: '  23.49   00023.49   00023.490000  103.45   0000103.45   0000103.45000    '
               23.49  23.49  ('', '', '', '', '23.49', '', '', '', '')
            00023.49  23.49  ('', '', '', '', '23.49', '', '', '', '')
        00023.490000  23.49  ('', '', '', '', '23.49', '', '', '', '')
              103.45  103.45  ('', '', '', '', '103.45', '', '', '', '')
          0000103.45  103.45  ('', '', '', '', '103.45', '', '', '', '')
       0000103.45000  103.45  ('', '', '', '', '103.45', '', '', '', '')

string: '  10003.45067   000010003.45067   000010003.4506700 '
         10003.45067  10003.45067  ('', '', '', '', '10003.45067', '', '', '', '')
     000010003.45067  10003.45067  ('', '', '', '', '10003.45067', '', '', '', '')
   000010003.4506700  10003.45067  ('', '', '', '', '10003.45067', '', '', '', '')

string: '  +15000.0012   +000015000.0012   +000015000.0012000    '
         +15000.0012  +15000.0012  ('+', '', '', '', '15000.0012', '', '', '', '')
     +000015000.0012  +15000.0012  ('+', '', '', '', '15000.0012', '', '', '', '')
  +000015000.0012000  +15000.0012  ('+', '', '', '', '15000.0012', '', '', '', '')

string: '  78000.89   000078000.89   000078000.89000    '
            78000.89  78000.89  ('', '', '', '', '78000.89', '', '', '', '')
        000078000.89  78000.89  ('', '', '', '', '78000.89', '', '', '', '')
     000078000.89000  78000.89  ('', '', '', '', '78000.89', '', '', '', '')

string: '  .0457e10   .0457000e10   00000.0457000e10  '
            .0457e10  0.0457e10  ('', '', '', '.0457', '', 'e', '10', '', '')
         .0457000e10  0.0457e10  ('', '', '', '.0457', '', 'e', '10', '', '')
    00000.0457000e10  0.0457e10  ('', '', '', '.0457', '', 'e', '10', '', '')

string: '   258e8   2580000e4   0000000002580000e4   '
               258e8  258e8  ('', '258', '', '', '', 'e', '8', '', '')
           2580000e4  2580000e4  ('', '2580000', '', '', '', 'e', '4', '', '')
  0000000002580000e4  2580000e4  ('', '2580000', '', '', '', 'e', '4', '', '')

string: '  0.782e10   0000.782e10   0000.7820000e10  '
            0.782e10  0.782e10  ('', '', '', '.782', '', 'e', '10', '', '')
         0000.782e10  0.782e10  ('', '', '', '.782', '', 'e', '10', '', '')
     0000.7820000e10  0.782e10  ('', '', '', '.782', '', 'e', '10', '', '')

string: '  1.23E2   0001.23E2  0001.2300000E2   '
              1.23E2  1.23E2  ('', '', '', '', '1.23', 'E', '2', '', '')
           0001.23E2  1.23E2  ('', '', '', '', '1.23', 'E', '2', '', '')
      0001.2300000E2  1.23E2  ('', '', '', '', '1.23', 'E', '2', '', '')

string: '  432e-102  0000432e-102   004320000e-106   '
            432e-102  432e-102  ('', '432', '', '', '', 'e-', '102', '', '')
        0000432e-102  432e-102  ('', '432', '', '', '', 'e-', '102', '', '')
      004320000e-106  4320000e-106  ('', '4320000', '', '', '', 'e-', '106', '', '')

string: '  1.46e10and0001.46e10  0001.4600000e10   '
             1.46e10  1.46e10  ('', '', '', '', '1.46', 'e', '10', '', '')
          0001.46e10  1.46e10  ('', '', '', '', '1.46', 'e', '10', '', '')
     0001.4600000e10  1.46e10  ('', '', '', '', '1.46', 'e', '10', '', '')

string: '  1.077e-300  0001.077e-300  0001.077000e-300   '
          1.077e-300  1.077e-300  ('', '', '', '', '1.077', 'e-', '300', '', '')
       0001.077e-300  1.077e-300  ('', '', '', '', '1.077', 'e-', '300', '', '')
    0001.077000e-300  1.077e-300  ('', '', '', '', '1.077', 'e-', '300', '', '')

string: '  1.069e10   0001.069e10   0001.069000e10   '
            1.069e10  1.069e10  ('', '', '', '', '1.069', 'e', '10', '', '')
         0001.069e10  1.069e10  ('', '', '', '', '1.069', 'e', '10', '', '')
      0001.069000e10  1.069e10  ('', '', '', '', '1.069', 'e', '10', '', '')

string: '  105040.03e10  000105040.03e10  105040.0300e10    '
        105040.03e10  105040.03e10  ('', '', '', '', '105040.03', 'e', '10', '', '')
     000105040.03e10  105040.03e10  ('', '', '', '', '105040.03', 'e', '10', '', '')
      105040.0300e10  105040.03e10  ('', '', '', '', '105040.03', 'e', '10', '', '')

string: '  +286E000024.487900  -78.4500e.14500   .0140E789.  '
  +286E000024.487900  +286E24.4879  ('+', '286', '', '', '', 'E', '', '', '24.4879')
     -78.4500e.14500  -78.45e0.145  ('-', '', '', '', '78.45', 'e', '', '.145', '')
          .0140E789.  0.014E789  ('', '', '', '.014', '', 'E', '789', '', '')

string: '  081,12.40E07,95.0120     0045,78,123.03500e-0.00  '
081,12.40E07,95.0120  81,12.4E7,95.012  ('', '', '', '', '81,12.4', 'E', '', '', '7,95.012')
   0045,78,123.03500  45,78,123.035  ('', '', '', '', '45,78,123.035', '', '', '', '')

string: '  0096,78,473.0380e-0.    0008,78,373.066000E0.    0004512300.E0000  '
    0096,78,473.0380  96,78,473.038  ('', '', '', '', '96,78,473.038', '', '', '', '')
  0008,78,373.066000  8,78,373.066  ('', '', '', '', '8,78,373.066', '', '', '', '')
         0004512300.  4512300  ('', '4512300', '', '', '', '', '', '', '')

string: '  ..18000  25..00 36...77   2..8  '
           No match,  No catched string,  No groups.

string: '  3.8..9    .12500.     12.51.400  '
           No match,  No catched string,  No groups.

string: '  00099,111.8713000   -0012,45,83,987.26+0.000,099,88,44.or00,00,00.00must'
   00099,111.8713000  99,111.8713  ('', '', '', '', '99,111.8713', '', '', '', '')
  -0012,45,83,987.26  -12,45,83,987.26  ('-', '', '', '', '12,45,83,987.26', '', '', '', '')
         00,00,00.00  0  ('', '', '0', '', '', '', '', '', '')

string: '  00099,44,and   0000,099,88,44.bom'
           00099,44,  99,44  ('', '99,44', '', '', '', '', '', '', '')
     0000,099,88,44.  99,88,44  ('', '99,88,44', '', '', '', '', '', '', '')

string: '00,000,00.587000  77,98,23,45.,  this,that '
    00,000,00.587000  0.587  ('', '', '', '.587', '', '', '', '', '')
        77,98,23,45.  77,98,23,45  ('', '77,98,23,45', '', '', '', '', '', '', '')

string: '  ,111  145.20  +9,9,9  0012800  .,,.  1  100,000 '
                ,111  111  ('', '111', '', '', '', '', '', '', '')
              145.20  145.2  ('', '', '', '', '145.2', '', '', '', '')
              +9,9,9  +9,9,9  ('+', '9,9,9', '', '', '', '', '', '', '')
             0012800  12800  ('', '12800', '', '', '', '', '', '', '')
                   1  1  ('', '1', '', '', '', '', '', '', '')
             100,000  100,000  ('', '100,000', '', '', '', '', '', '', '')

string: '1,1,1.111  000,001.111   -999.  0.  111.110000  1.1.1.111  9.909,888'
           1,1,1.111  1,1,1.111  ('', '', '', '', '1,1,1.111', '', '', '', '')
         000,001.111  1.111  ('', '', '', '', '1.111', '', '', '', '')
               -999.  -999  ('-', '999', '', '', '', '', '', '', '')
                  0.  0  ('', '0', '', '', '', '', '', '', '')
          111.110000  111.11  ('', '', '', '', '111.11', '', '', '', '')
eyquem
la source
8

L'expression régulière ci-dessous correspondra aux deux nombres de votre exemple.

\b\d[\d,.]*\b

Il renverra 5000 et 99 999,99998713 - correspondant à vos besoins.

Leons
la source
3
Cela correspondra à la virgule dans this,that.
Justin Morgan
@Justin Morgan - vous avez raison, je n'ai pas testé cette condition. Voici une version mise à jour qui fonctionnera pour tous les cas, à l'exception d'un nombre commençant par une virgule ou un point. \b\d[\d,.]+\b
Leons
Beaucoup mieux, mais cela permettra toujours 9....9ou 1,,,,X(bien que le X ne soit pas inclus dans le match).
Justin Morgan
1
Au fait, \b\d[\d,.]*\best suffisamment proche pour que si vous modifiez votre réponse, je supprime le -1. Cela devrait être un * au lieu d'un + cependant; \b\d[\d,.]+\bn'autorisera pas les nombres à un chiffre.
Justin Morgan
@Justin Morgan - merci pour la perspicacité. Cette question était nettement plus complexe qu'il n'y paraissait. J'ai mis à jour ma réponse en fonction de vos commentaires - c'est logique.
Leons
3

Prenant une certaine liberté avec les exigences, vous recherchez

\d+([\d,]?\d)*(\.\d+)?

Mais notez que cela correspondra par exemple 11,11,1

entonio
la source
Par curiosité, est - il une raison quelconque vous êtes allé avec au \d+([\d,]?\d)*(\.\d+)?lieu de \d+(,\d+)*(\.\d+)?? Je pense qu'ils donneraient des correspondances équivalentes, même si les groupes de capture seraient différents.
Justin Morgan
Salut. Aucune raison particulière, c'était un problème de départ avec une expression plus complexe afin de ne pas correspondre aux formats invalides.
entonio
3
\d+(,\d+)*(\.\d+)?

Cela suppose qu'il y a toujours au moins un chiffre avant ou après une virgule ou une décimale et suppose également qu'il y a au plus une décimale et que toutes les virgules précèdent la virgule.

Neil
la source
2
Cela ne limite pas les groupes de virgules au format à 3 chiffres. Il acceptera 999999,9,9,9,9.
Justin Morgan
Bien que je devrais probablement souligner que c'est plus proche d'être correct que la plupart des autres. Votre -1 ne vient pas de moi.
Justin Morgan
C'est le RE que j'utiliserais, bien qu'avec une autre étape de validation après (peut-être pas avec un RE); essayer de tout faire avec un seul RE rend la vie beaucoup plus difficile.
Donal Fellows
@Justin Morgan Il n'était pas clair que la virgule n'était acceptée que dans les groupes à 3 chiffres. Mais c'est facilement résolu en changeant (,\d+)en (,\d\d\d)je suppose.
Neil
2

Cette expression régulière:

(\d{1,3},\d{3}(,\d{3})*)(\.\d*)?|\d+\.?\d*

Correspond à chaque nombre de la chaîne:

1 1,0 0,1 1,001 1,000 1,000,000 1000,1 1,000,1 1,323,444,000 1,999 1,222,455,666,0 1,244

Eric D
la source
2

Voici une regex:

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

qui accepte les nombres:

  • sans espaces et / ou décimales, par ex. 123456789,123.123
  • avec des virgules ou des espaces comme séparateur de milliers et / ou décimales, par exemple. 123 456 789, 123 456 789.100, 123,456,3,232,300,000.00

Tests: http://regexr.com/3h1a2

Kacper Cz
la source
Cela fonctionne bien sur regexr.com mais dans le module python re, cela ne fonctionne pas
Pardhu
1

Voici une autre construction qui commence par le format numérique le plus simple puis, de manière non superposée, ajoute progressivement des formats numériques plus complexes:

Regep Java:

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

En tant que chaîne Java (notez que le \ nécessaire pour échapper à \ et. Puisque \ et. Ont une signification particulière dans une expression rationnelle lorsqu'ils sont seuls):

String myregexp="(\\d)|([1-9]\\d+)|(\\.\\d+)|(\\d\\.\\d*)|([1-9]\\d+\\.\\d*)|([1-9]\\d{0,2}(,\\d{3})+(\\.\\d*)?)";   

Explication:

  1. Cette expression rationnelle a la forme A | B | C | D | E | F où A, B, C, D, E, F sont elles-mêmes des expressions rationnelles qui ne se chevauchent pas. En général, je trouve plus facile de commencer avec les correspondances les plus simples possibles, A. Si A manque les correspondances que vous voulez, créez un B qui est une modification mineure de A et comprend un peu plus de ce que vous voulez. Ensuite, sur la base de B, créez un C qui attrape plus, etc. il est plus facile de comprendre une expression rationnelle avec 20 expressions rationnelles simples sans chevauchement connectées avec des OR plutôt que quelques expressions rationnelles avec des correspondances plus complexes. Mais, chacun à lui!

  2. A est (\ d) et correspond exactement à l'un des 0,1,2,3,4,5,6,7,8,9, ce qui ne peut pas être plus simple!

  3. B est ([1-9] \ d +) et ne correspond qu'aux nombres de 2 chiffres ou plus, le premier excluant 0. B correspond exactement à l'un des 10,11,12, ... B ne chevauche pas A mais est une petite modification de A.

  4. C est (. \ D +) et correspond uniquement à une décimale suivie d'un ou plusieurs chiffres. C correspond exactement à l'un des .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .00 .01 .02 .... .23000 ... C autorise les éros à droite ce que je préfère: s'il s'agit de données de mesure, le nombre de zéros de fin indique le niveau de précision. Si vous ne voulez pas les zéros de fin à droite, remplacez (. \ D +) par (. \ D * [1-9]) mais cela exclut également .0 qui, je pense, devrait être autorisé. C est également une petite modification de A.

  5. D est (\ d. \ D *) qui est A plus les décimales avec des zéros à droite. D ne correspond qu'à un seul chiffre, suivi d'une décimale, suivi de zéro ou plusieurs chiffres. D correspond à 0. 0,0 0,1 0,2 .... 0,01000 ... 9. 9.0 9.1..0.0230000 .... 9.9999999999 ... Si vous souhaitez exclure "0." puis changez D en (\ d. \ d +). Si vous voulez exclure les zéros de fin à droite, changez D en (\ d. \ D * [1-9]) mais cela exclut 2.0 qui, je pense, devrait être inclus. D ne chevauche pas A, B ou C.

  6. E est ([1-9] \ d +. \ D *) qui est B plus les décimales avec des zéros à droite. Si vous souhaitez exclure "13.", par exemple, remplacez E par ([1-9] \ d +. \ D +). E ne chevauche pas A, B, C ou D. E correspond à 10. 10.0 10.0100 .... 99.9999999999 ... Les zéros de fin peuvent être traités comme dans 4. et 5.

  7. F est ([1-9] \ d {0,2} (, \ d {3}) + (. \ D *)?) Et ne fait correspondre que les nombres avec des virgules et éventuellement des décimales autorisant les zéros de fin à droite. Le premier groupe ([1-9] \ d {0,2}) correspond à un chiffre différent de zéro suivi de zéro, un ou deux chiffres supplémentaires. Le deuxième groupe (, \ d {3}) + correspond à un groupe de 4 caractères (une virgule suivie d'exactement trois chiffres) et ce groupe peut correspondre une ou plusieurs fois (pas de correspondance signifie pas de virgule!). Enfin, (. \ D *)? ne correspond à rien ou correspond. par lui-même, ou correspond à une décimale. suivi d'un nombre quelconque de chiffres, éventuellement aucun. Encore une fois, pour exclure des éléments tels que «1,111.», Remplacez (. \ D *) par (. \ D +). Les zéros de fin peuvent être traités comme en 4. ou 5. F ne chevauche pas A, B, C, D ou E. Je ne pourrais pas penser à une expression rationnelle plus facile pour F.

Faites-moi savoir si vous êtes intéressé et je peux modifier ci-dessus pour gérer les zéros de fin à droite comme vous le souhaitez.

Voici ce qui correspond à l'expression rationnelle et ce qui ne fonctionne pas:

0
1
02 <- invalid
20
22
003 <- invalid
030 <- invalid
300
033 <- invalid
303
330
333
0004 <- invalid
0040 <- invalid
0400 <- invalid
4000
0044 <- invalid
0404 <- invalid
0440 <- invalid
4004
4040
4400
0444 <- invalid
4044
4404
4440
4444
00005 <- invalid
00050 <- invalid
00500 <- invalid
05000 <- invalid
50000
00055 <- invalid
00505 <- invalid
00550 <- invalid
05050 <- invalid
05500 <- invalid
50500
55000
00555 <- invalid
05055 <- invalid
05505 <- invalid
05550 <- invalid
50550
55050
55500
. <- invalid
.. <- invalid
.0
0.
.1
1.
.00
0.0
00. <- invalid
.02
0.2
02. <- invalid
.20
2.0
20.
.22
2.2
22.
.000
0.00
00.0 <- invalid
000. <- invalid
.003
0.03
00.3 <- invalid
003. <- invalid
.030
0.30
03.0 <- invalid
030. <- invalid
.033
0.33
03.3 <- invalid
033. <- invalid
.303
3.03
30.3
303.
.333
3.33
33.3
333.
.0000
0.000
00.00 <- invalid
000.0 <- invalid
0000. <- invalid
.0004
0.0004
00.04 <- invalid
000.4 <- invalid
0004. <- invalid
.0044
0.044
00.44 <- invalid
004.4 <- invalid
0044. <- invalid
.0404
0.404
04.04 <- invalid
040.4 <- invalid
0404. <- invalid
.0444
0.444
04.44 <- invalid
044.4 <- invalid
0444. <- invalid
.4444
4.444
44.44
444.4
4444.
.00000
0.0000
00.000 <- invalid
000.00 <- invalid
0000.0 <- invalid
00000. <- invalid
.00005
0.0005
00.005 <- invalid
000.05 <- invalid
0000.5 <- invalid
00005. <- invalid
.00055
0.0055
00.055 <- invalid
000.55 <- invalid
0005.5 <- invalid
00055. <- invalid
.00505
0.0505
00.505 <- invalid
005.05 <- invalid
0050.5 <- invalid
00505. <- invalid
.00550
0.0550
00.550 <- invalid
005.50 <- invalid
0055.0 <- invalid
00550. <- invalid
.05050
0.5050
05.050 <- invalid
050.50 <- invalid
0505.0 <- invalid
05050. <- invalid
.05500
0.5500
05.500 <- invalid
055.00 <- invalid
0550.0 <- invalid
05500. <- invalid
.50500
5.0500
50.500
505.00
5050.0
50500.
.55000
5.5000
55.000
550.00
5500.0
55000.
.00555
0.0555
00.555 <- invalid
005.55 <- invalid
0055.5 <- invalid
00555. <- invalid
.05055
0.5055
05.055 <- invalid
050.55 <- invalid
0505.5 <- invalid
05055. <- invalid
.05505
0.5505
05.505 <- invalid
055.05 <- invalid
0550.5 <- invalid
05505. <- invalid
.05550
0.5550
05.550 <- invalid
055.50 <- invalid
0555.0 <- invalid
05550. <- invalid
.50550
5.0550
50.550
505.50
5055.0
50550.
.55050
5.5050
55.050
550.50
5505.0
55050.
.55500
5.5500
55.500
555.00
5550.0
55500.
.05555
0.5555
05.555 <- invalid
055.55 <- invalid
0555.5 <- invalid
05555. <- invalid
.50555
5.0555
50.555
505.55
5055.5
50555.
.55055
5.5055
55.055
550.55
5505.5
55055.
.55505
5.5505
55.505
555.05
5550.5
55505.
.55550
5.5550
55.550
555.50
5555.0
55550.
.55555
5.5555
55.555
555.55
5555.5
55555.
, <- invalid
,, <- invalid
1, <- invalid
,1 <- invalid
22, <- invalid
2,2 <- invalid
,22 <- invalid
2,2, <- invalid
2,2, <- invalid
,22, <- invalid
333, <- invalid
33,3 <- invalid
3,33 <- invalid
,333 <- invalid
3,33, <- invalid
3,3,3 <- invalid
3,,33 <- invalid
,,333 <- invalid
4444, <- invalid
444,4 <- invalid
44,44 <- invalid
4,444
,4444 <- invalid
55555, <- invalid
5555,5 <- invalid
555,55 <- invalid
55,555
5,5555 <- invalid
,55555 <- invalid
666666, <- invalid
66666,6 <- invalid
6666,66 <- invalid
666,666
66,6666 <- invalid
6,66666 <- invalid
66,66,66 <- invalid
6,66,666 <- invalid
,666,666 <- invalid
1,111.
1,111.11
1,111.110
01,111.110 <- invalid
0,111.100 <- invalid
11,11. <- invalid
1,111,.11 <- invalid
1111.1,10 <- invalid
01111.11,0 <- invalid
0111.100, <- invalid
1,111,111.
1,111,111.11
1,111,111.110
01,111,111.110 <- invalid
0,111,111.100 <- invalid
1,111,111.
1,1111,11.11 <- invalid
11,111,11.110 <- invalid
01,11,1111.110 <- invalid
0,111111.100 <- invalid
0002,22.2230 <- invalid
.,5.,., <- invalid
2.0,345,345 <- invalid
2.334.456 <- invalid
David Alexander
la source
1
\b\d+,

\ b -------> limite de mot

\ d + ------> un ou chiffre

, --------> contenant des virgules,

Par exemple:

sddsgg 70 000 sdsfdsf fdgfdg70,00

sfsfsd 5,44,4343 5,7788,44 555

Il correspondra:

70,

5,

44,

, 44

Ibz.Shaikh
la source
0
(,*[\d]+,*[\d]*)+

Cela correspondrait à n'importe quel petit ou grand nombre comme suit avec ou sans virgule

1
100
1,262
1,56,262
10,78,999
12,34,56,789

ou

1
100
1262
156262
1078999
123456789
phpnerd
la source