Espressione regolare per abbinare i numeri con o senza virgole e decimali nel testo


97

Sto cercando di individuare e sostituire tutti i numeri in un corpo di testo. Ho trovato alcune espressioni regolari di esempio, che quasi risolvono il problema, ma nessuna è ancora perfetta. Il problema che ho è che i numeri nel mio testo possono o meno avere decimali e virgole. Per esempio:

"La volpe da 5000 libbre ha scavalcato un recinto di 99.999,99998713 piedi."

La regex dovrebbe restituire " 5000" e " 99,999.99998713". Esempi che ho trovato suddividono i numeri sulla virgola o sono limitati a due cifre decimali. Sto iniziando a capire abbastanza espressioni regolari per capire perché alcuni esempi sono limitati a due cifre decimali, ma non ho ancora imparato come superarlo e includere anche la virgola per ottenere l'intera sequenza.

Ecco la mia ultima versione:

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

Che restituisce " 5000", " 99,99", " 9.99" e " 998713" per il testo sopra.


1
Quale linguaggio di programmazione o sapore regex?
Matt Ball

7
Sembra che quasi tutte le risposte qui commettono l'errore di consentire cose come .,.,.o 9,9,9,9o 9,9.99.9. Queste regex non richiedono che i numeri siano nel formato corretto e, nel peggiore dei casi, tratteranno la punteggiatura come numeri. Sono possibili alcune modifiche opzionali (ad esempio se consentire gli zeri iniziali e finali), ma alcune delle risposte che vedo sono decisamente errate. Non mi piace davvero il downvoting, specialmente sui tentativi onesti, ma sento che le risposte qui devono essere pulite. Questa è una domanda comune e verrà sicuramente posta di nuovo.
Justin Morgan

Se non lo conosci, dai un'occhiata a regexpal.com
entonio

Scusa per il ritardo Matt. Sto usando Adobe ActionScript 3. Pensavo che il comportamento regex fosse lo stesso di JavaScript, ma ho testato il suggerimento di Justin su regexpal.com e l'ho confrontato con i risultati della mia applicazione Flash e ho visto due risultati diversi entrambi sbagliati.

Questa volta dovrebbe funzionare, sulla base dei miei test. Fammi sapere se ha ancora bisogno di raffinamento.
Justin Morgan

Risposte:


289

EDIT: Dal momento che questo ha ottenuto molte visualizzazioni, vorrei iniziare dando a tutti ciò per cui hanno cercato su 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])?$

Ora che è fuori mano, la maggior parte di quanto segue è inteso come commento su quanto può diventare complesso regex se cerchi di essere intelligente con esso, e perché dovresti cercare alternative. Leggi a proprio rischio.


Questo è un compito molto comune, ma tutte le risposte che vedo qui finora accetterà input che non corrispondono al formato numeri, ad esempio ,111, 9,9,9o anche .,,.. È abbastanza semplice da correggere, anche se i numeri sono incorporati in altro testo. IMHO tutto ciò che non riesce a tirare 1,234.56 e 1234- e solo quei numeri -out di abc22 1,234.56 9.9.9.9 def 1234è una risposta sbagliata.

Prima di tutto, se non hai bisogno di fare tutto questo in una regex, non farlo. Una singola regex per due diversi formati di numeri è difficile da mantenere anche quando non sono incorporati in altro testo. Quello che dovresti davvero fare è dividere il tutto su spazi bianchi, quindi eseguire due o tre espressioni regolari più piccole sui risultati. Se questa non è un'opzione per te, continua a leggere.

Modello di base

Considerando gli esempi che hai fornito, ecco una semplice regex che consente praticamente qualsiasi formato intero o decimale 0000e blocca tutto il resto:

^\d*\.?\d+$

Eccone uno che richiede il 0,000formato:

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

Mettili insieme e le virgole diventano facoltative fintanto che sono coerenti:

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

Numeri incorporati

I modelli sopra richiedono che l'intero input sia un numero. Stai cercando numeri incorporati nel testo, quindi devi allentare quella parte. D'altra parte, non vuoi che veda catch22e pensi che abbia trovato il numero 22. Se stai usando qualcosa con supporto lookbehind (come .NET), questo è abbastanza semplice: sostituisci ^con (?<!\S)e $con (?!\S)e sei a posto andare:

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

Se lavori con JavaScript o Ruby o qualcosa del genere, le cose iniziano a sembrare più complesse:

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

Dovrai usare i gruppi di cattura; Non riesco a pensare ad un'alternativa senza guardare dietro il supporto. I numeri che vuoi saranno nel Gruppo 1 (supponendo che l'intera partita sia del Gruppo 0).

Validazione e regole più complesse

Penso che questo copra la tua domanda, quindi se è tutto ciò di cui hai bisogno, smetti di leggere ora. Se vuoi diventare più elaborato, le cose diventano molto complesse molto rapidamente. A seconda della situazione, potresti voler bloccare alcuni o tutti i seguenti:

  • Input vuoto
  • Zeri iniziali (ad esempio 000123)
  • Zeri finali (ad esempio 1.2340000)
  • Decimali che iniziano con il punto decimale (ad es. .001 invece di 0.001)

Per il gusto di farlo, supponiamo che tu voglia bloccare i primi 3, ma consenti l'ultimo. Cosa dovresti fare? Ti dirò cosa dovresti fare, dovresti usare una regex diversa per ogni regola e restringere progressivamente le tue corrispondenze. Ma per il bene della sfida, ecco come fai tutto in un unico schema gigante:

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

Ed ecco cosa significa:

(?<!\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.

Testato qui: http://rextester.com/YPG96786

Ciò consentirà cose come:

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

Bloccherà cose come:

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

Ci sono diversi modi per rendere questa regex più semplice e più breve, ma comprendi che la modifica del pattern allenterà ciò che considera un numero.

Poiché molti motori di regex (ad esempio JavaScript e Ruby) non supportano il lookbehind negativo, l'unico modo per farlo correttamente è con i gruppi di cattura:

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

I numeri che stai cercando saranno nel gruppo di cattura 1.

Testato qui: http://rubular.com/r/3HCSkndzhT

Una nota finale

Ovviamente, questa è una regex massiccia, complicata, quasi illeggibile. Mi è piaciuta la sfida, ma dovresti considerare se vuoi davvero usarlo in un ambiente di produzione. Invece di provare a fare tutto in un unico passaggio, potresti farlo in due: un'espressione regolare per catturare tutto ciò che potrebbe essere un numero, quindi un'altra per eliminare tutto ciò che non è un numero. Oppure potresti eseguire alcune elaborazioni di base, quindi utilizzare le funzioni di analisi dei numeri integrate nella tua lingua. La tua scelta.


1
Questo è un ottimo tentativo, ma potrebbe esserci un problema: a seconda dell'avidità del motore, un dato numero può corrispondere parzialmente a due dei formati concorrenti, invece di abbinare singolarmente quello corretto - ad esempio 5000 può produrre più di 500 0 Questo mi rende un po 'scettico riguardo al tentativo di coprire troppo con una sola espressione, ed è per questo che ho dato una risposta più semplice con l'avvertenza di possibili falsi positivi. Alla fine della giornata, il rigore dei requisiti dovrebbe dettare la soluzione.
entonio

@entonio - Questo è un punto giusto. Potrebbe funzionare con l'ultima modifica. A proposito, il tuo voto negativo non era da parte mia, dal momento che hai indicato la potenziale corrispondenza 1,11,11.
Justin Morgan

Sto usando ActionScript, che credo si comporti allo stesso modo di JavaScript. Utilizzando il primo pattern che hai consigliato, ottengo i seguenti risultati sulla mia stringa di prova (per la convalida, sto semplicemente restituendo le corrispondenze racchiuse in "<< [risultato] >>"): La volpe << 5 >> 000 lb. ha saltato un << 9 >> 9 <<, 9 >> <<99>> <<. 9 >> <<99>> <<98>> <<71>> recinzione di 3 piedi.

2
Bene, uno dei tuoi voti positivi è da parte mia :) poiché penso che la tua risposta sia quanto più completa possibile e tu ci metti del lavoro. Giusto per renderlo un contenuto-commento, una nota all'OP, il?: All'inizio dei gruppi c'è in modo che non vengano restituiti autonomamente nel risultato ('catturato'), anche se contribuiscono all'abbinamento di l'intera espressione; ogni numero formattato nell'input corrisponde all'intera espressione.
entonio

@Michael e @entonio - Vedi l'ultima modifica, che sembra funzionare. Questo è uno di quei problemi di regex che sono più difficili di quanto sembri.
Justin Morgan,

10

Alcuni giorni fa, ho lavorato al problema di rimuovere gli zeri finali dalla stringa di un numero .

Nella continuità di quel problema, trovo questo interessante perché allarga il problema ai numeri composti da virgole.

Ho preso lo schema della regex che avevo scritto in quel problema precedente su cui ho lavorato e l'ho migliorato in modo che possa trattare i numeri con virgole come una risposta a questo problema.

Sono stato portato via dal mio entusiasmo e dal mio gusto per le regex. Non so se il risultato corrisponda esattamente alla necessità espressa da Michael Prescott. Sarei interessato a conoscere i punti che sono in eccesso o in difetto nella mia regex, e correggerla per renderla più adatta a te.

Ora, dopo una lunga sessione di lavoro su questa regex, ho una sorta di peso nel cervello, quindi non sono abbastanza fresco per dare molte spiegazioni. Se i punti sono oscuri e se qualcuno può interessarsi abbastanza, per favore, chiedimi.

La regex è costruita in modo da poter rilevare i numeri espressi nella notazione scientifica 2E10 o anche 5,22,454.12E-00.0478 , rimuovendo anche gli zeri non necessari nelle due parti di tali numeri. Se un esponente è uguale a zero, il numero viene modificato in modo che non ci sia più esponente.

Ho inserito un po 'di verifica nel pattern in modo che alcuni casi particolari non corrispondano, ad esempio " 12 ..57 " non corrisponderanno. Ma in ", 111" la stringa "111" corrisponde perché la virgola precedente è considerata una virgola non contenuta in un numero ma una virgola di frase.

Penso che la gestione delle virgole dovrebbe essere migliorata, perché mi sembra che ci siano solo 2 cifre tra le virgole nella numerazione indiana. Non sarà difficile correggere, presumo

Di seguito è riportato un codice che mostra come funziona la mia regex. Ci sono due funzioni, a seconda che si voglia trasformare i numeri ".1245" in "0.1245" oppure no. Non sarei sorpreso se per certi casi di stringhe di numeri rimarranno errori, corrispondenze o non corrispondenze indesiderate; poi mi piacerebbe conoscere questi casi per capire e correggere la carenza.

Mi scuso per questo codice scritto in Python, ma le regex sono translangage e penso che tutti saranno in grado di comprendere lo schema del 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

risultato

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', '', '', '', '')

8

L'espressione regolare di seguito corrisponderà a entrambi i numeri del tuo esempio.

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

Restituirà 5000 e 99,999,99998713, corrispondenti alle tue esigenze.


3
Questo corrisponderà alla virgola in this,that.
Justin Morgan

@Justin Morgan - hai ragione, non ho testato quella condizione. Ecco una versione aggiornata che funzionerà per tutti i casi, ad eccezione di un numero che inizia con una virgola o un punto. \b\d[\d,.]+\b
Leons

Molto meglio, ma consentirà comunque 9....9o 1,,,,X(sebbene la X non sarà inclusa nella partita).
Justin Morgan

1
A proposito, \b\d[\d,.]*\bè abbastanza vicino che se modifichi la tua risposta rimuoverò -1. Tuttavia, dovrebbe essere un * invece di un +; \b\d[\d,.]+\bnon consentirà numeri a una cifra.
Justin Morgan

@Justin Morgan - grazie per l'intuizione. Questa domanda era decisamente più complessa di quanto apparisse. Ho aggiornato la mia risposta in base al tuo feedback: ha senso.
Leons

3

Prendendoti una certa libertà con i requisiti che stai cercando

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

Ma nota che questo corrisponderà ad es. 11,11,1


Per curiosità, c'è qualche motivo per cui sei andato \d+([\d,]?\d)*(\.\d+)?invece di \d+(,\d+)*(\.\d+)?? Penso che darebbero corrispondenze equivalenti, anche se i gruppi di cattura sarebbero diversi.
Justin Morgan

Ciao. Nessun motivo speciale, è stato un ritardo nell'iniziare con un'espressione più complessa per non corrispondere a formati non validi.
entonio

3
\d+(,\d+)*(\.\d+)?

Ciò presuppone che ci sia sempre almeno una cifra prima o dopo ogni virgola o decimale e presuppone inoltre che ci sia al massimo un decimale e che tutte le virgole precedano il decimale.


2
Ciò non limita i gruppi di virgole al formato a 3 cifre. Accetterà 999999,9,9,9,9.
Justin Morgan

Anche se probabilmente dovrei sottolineare che questo è più vicino all'essere corretto della maggior parte degli altri. Il tuo -1 non è da parte mia.
Justin Morgan

Questa è la RE che userei, anche se con un altro passaggio di convalida successivo (possibilmente non con una RE); provare a fare tutto con una RE rende la vita molto più difficile.
Donal Fellows

@Justin Morgan Non era chiaro che la virgola fosse accettata solo nei gruppi di 3 cifre. Ma è facilmente risolvibile cambiando (,\d+)in (,\d\d\d)immagino.
Neil

2

Questa regex:

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

Corrisponde a ogni numero nella stringa:

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


2

Ecco una regex:

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

che accetta numeri:

  • senza spazi e / o decimali, es. 123456789,123.123
  • con virgole o spazi come separatori delle migliaia e / o decimali, ad es. 123 456 789, 123 456 789.100, 123,456,3,232,300,000.00

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


Funziona bene su regexr.com ma nel modulo re python non funziona
Pardhu

1

Ecco un'altra costruzione che inizia con il formato numerico più semplice e poi, in modo non sovrapposto, aggiunge progressivamente formati numerici più complessi:

Regep Java:

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

Come una stringa Java (nota l'ulteriore \ necessario per eseguire l'escape in \ e. Da \ e. Hanno un significato speciale in un'espressione regolare quando da soli):

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

Spiegazione:

  1. Questa regexp ha la forma A | B | C | D | E | F dove A, B, C, D, E, F sono esse stesse espressioni regolari che non si sovrappongono. In generale, trovo più facile iniziare con le partite più semplici possibili, A. Se A manca le partite che desideri, crea una B che sia una modifica minore di A e includa un po 'di più di ciò che desideri. Quindi, in base a B, crea una C che cattura di più, ecc. Trovo anche più facile creare espressioni regolari che non si sovrappongono; è più facile capire una regexp con 20 semplici espressioni regolari non sovrapposte connesse con OR piuttosto che poche espressioni regolari con corrispondenze più complesse. Ma ognuno per conto suo!

  2. A è (\ d) e corrisponde esattamente a 0,1,2,3,4,5,6,7,8,9 che non può essere più semplice!

  3. B è ([1-9] \ d +) e corrisponde solo ai numeri con 2 o più cifre, il primo esclude lo 0. B corrisponde esattamente a uno di 10,11,12, ... B non si sovrappone ad A ma è una piccola modifica di A.

  4. C è (. \ D +) e corrisponde solo a un decimale seguito da una o più cifre. C corrisponde esattamente a .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .00 .01 .02 .... .23000 ... C consente l'eros finale a destra che preferisco: se si tratta di dati di misura, il numero di zeri finali indica il livello di precisione. Se non vuoi gli zeri finali a destra, cambia (. \ D +) in (. \ D * [1-9]) ma questo esclude anche .0 che penso dovrebbe essere consentito. C è anche una piccola modifica di A.

  5. D è (\ d. \ D *) che è A più decimali con zeri finali a destra. D corrisponde solo a una singola cifra, seguita da un decimale, seguito da zero o più cifre. D corrisponde a 0. 0.0 0.1 0.2 .... 0.01000 ... 9. 9.0 9.1..0.0230000 .... 9.9999999999 ... Se vuoi escludere "0" quindi cambia D in (\ d. \ d +). Se vuoi escludere gli zeri finali a destra, cambia D in (\ d. \ D * [1-9]) ma questo esclude 2.0 che penso dovrebbe essere incluso. D non si sovrappone ad A, B o C.

  6. E è ([1-9] \ d +. \ D *) che è B più decimali con zeri finali a destra. Ad esempio, se desideri escludere "13.", modifica E in ([1-9] \ d +. \ D +). E non si sovrappone ad A, B, C o D. E corrisponde a 10. 10.0 10.0100 .... 99.9999999999 ... Gli zeri finali possono essere gestiti come in 4. e 5.

  7. F è ([1-9] \ d {0,2} (, \ d {3}) + (. \ D *)?) E trova solo numeri con virgole e possibilmente decimali che consentono zeri finali a destra. Il primo gruppo ([1-9] \ d {0,2}) corrisponde a una cifra diversa da zero seguita da zero, una o due cifre in più. Il secondo gruppo (, \ d {3}) + corrisponde a un gruppo di 4 caratteri (una virgola seguita esattamente da tre cifre) e questo gruppo può corrispondere una o più volte (nessuna corrispondenza significa nessuna virgola!). Infine, (. \ D *)? non corrisponde a nulla o corrisponde a. da solo o corrisponde a un decimale. seguito da un numero qualsiasi di cifre, possibilmente nessuna. Di nuovo, per escludere cose come "1,111.", Cambia (. \ D *) in (. \ D +). Gli zeri finali possono essere gestiti come in 4. o 5. F non si sovrappone ad A, B, C, D o E. Non riuscivo a pensare a un'espressione regolare più semplice per F.

Fammi sapere se sei interessato e posso modificare sopra per gestire gli zeri finali a destra come desiderato.

Ecco cosa corrisponde a regexp e cosa no:

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

1
\b\d+,

\ b -------> confine di parola

\ d + ------> uno o una cifra

, --------> contenente virgole,

Per esempio:

sddsgg 70.000 sdsfdsf fdgfdg70,00

sfsfsd 5,44,4343 5.7788,44 555

Corrisponderà:

70,

5,

44,

, 44


0
(,*[\d]+,*[\d]*)+

Ciò corrisponderebbe a qualsiasi numero piccolo o grande come segue con o senza virgola

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

o

1
100
1262
156262
1078999
123456789
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.