TL; DR
Utilizzare [.]invece di \.e [0-9]invece di \dper evitare problemi di escape in alcuni linguaggi (come Java).
Grazie a quello senza nome per averlo riconosciuto originariamente.
Un modello relativamente semplice per la corrispondenza di un numero in virgola mobile è
[+-]?([0-9]*[.])?[0-9]+
Questo corrisponderà:
Guarda un esempio funzionante
Se vuoi anche trovare una corrispondenza 123.(un punto senza parte decimale), allora avrai bisogno di un'espressione leggermente più lunga:
[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)
Vedi la risposta di pkeller per una spiegazione più completa di questo schema
Se desideri includere numeri non decimali, come esadecimali e ottali, vedi la mia risposta a Come faccio a identificare se una stringa è un numero? .
Se vuoi convalidare che un input è un numero (piuttosto che trovare un numero all'interno dell'input), allora dovresti circondare il pattern con ^e $, in questo modo:
^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$
Espressioni regolari irregolari
Le "espressioni regolari", implementate nella maggior parte dei linguaggi moderni, API, framework, librerie, ecc., Sono basate su un concetto sviluppato nella teoria del linguaggio formale . Tuttavia, gli ingegneri del software hanno aggiunto molte estensioni che portano queste implementazioni ben oltre la definizione formale. Quindi, sebbene la maggior parte dei motori di espressioni regolari si somiglino, in realtà non esiste uno standard. Per questo motivo, molto dipende da quale lingua, API, framework o libreria stai utilizzando.
(Per inciso, per ridurre la confusione, molti hanno deciso di utilizzare " regex " o " regexp " per descrivere questi linguaggi di corrispondenza migliorati. Per ulteriori informazioni, vedere Espressione regolare è uguale a un'espressione regolare? Su RexEgg.com.)
Detto questo, la maggior parte dei motori regex (in realtà, tutti, per quanto ne so) accetterebbe \.. Molto probabilmente, c'è un problema con la fuga.
Il problema della fuga
Alcuni linguaggi hanno il supporto integrato per le espressioni regolari, come JavaScript . Per quelle lingue che non lo fanno, la fuga può essere un problema.
Questo perché fondamentalmente stai codificando in una lingua all'interno di una lingua. Java, ad esempio, utilizza \come carattere di escape all'interno delle sue stringhe, quindi se desideri inserire un carattere letterale barra rovesciata all'interno di una stringa, devi eseguirne l'escape:
// creates a single character string: "\"
String x = "\\";
Tuttavia, le espressioni regolari usano anche il \carattere per l'escape, quindi se vuoi abbinare un \carattere letterale , devi eseguirne l'escape per il motore regexe, quindi eseguire nuovamente l'escape per Java:
// Creates a two-character string: "\\"
// When used as a regex pattern, will match a single character: "\"
String regexPattern = "\\\\";
Nel tuo caso, probabilmente non sei sfuggito al carattere backslash nel linguaggio in cui stai programmando:
// will most likely result in an "Illegal escape character" error
String wrongPattern = "\.";
// will result in the string "\."
String correctPattern = "\\.";
Tutta questa fuga può creare molta confusione. Se la lingua con cui stai lavorando supporta stringhe grezze , dovresti usarle per ridurre il numero di barre rovesciate, ma non tutte le lingue lo fanno (in particolare: Java). Fortunatamente, c'è un'alternativa che funzionerà qualche volta:
String correctPattern = "[.]";
Per un motore regex, \.e [.]significa esattamente la stessa cosa. Nota che questo non funziona in tutti i casi, come newline ( \\n), parentesi quadra aperta ( \\[) e backslash ( \\\\o [\\]).
Una nota sui numeri corrispondenti
(Suggerimento: è più difficile di quanto pensi)
Abbinare un numero è una di quelle cose che penseresti sia abbastanza facile con regex, ma in realtà è piuttosto complicato. Diamo un'occhiata al tuo approccio, pezzo per pezzo:
[-+]?
Abbina un -o+
[0-9]*
Trova 0 o più cifre sequenziali
\.?
Abbina un optional .
[0-9]*
Trova 0 o più cifre sequenziali
Innanzitutto, possiamo ripulire un po 'questa espressione usando una scorciatoia di classe di caratteri per le cifre (nota che questo è anche suscettibile al problema di escape menzionato sopra):
[0-9] = \d
Lo userò di \dseguito, ma tieni presente che significa la stessa cosa di [0-9]. (Beh, in realtà, in alcuni motori \dcorrisponderà alle cifre di tutti gli script, quindi corrisponderà più di quanto [0-9]farà, ma probabilmente non è significativo nel tuo caso.)
Ora, se lo guardi attentamente, ti renderai conto che ogni singola parte del tuo modello è opzionale . Questo modello può corrispondere a una stringa di lunghezza 0; una stringa composta solo da +o -; oppure, una stringa composta solo da a .. Questo probabilmente non è quello che intendevi.
Per risolvere questo problema, è utile iniziare "ancorando" la tua regex con la stringa minima richiesta, probabilmente una singola cifra:
\d+
Ora vogliamo aggiungere la parte decimale, ma non va dove pensi che potrebbe:
\d+\.?\d* /* This isn't quite correct. */
Ciò corrisponderà comunque a valori come 123.. Peggio ancora, ha una sfumatura malvagia . Il punto è facoltativo, il che significa che hai due classi ripetute fianco a fianco ( \d+e \d*). Questo può effettivamente essere pericoloso se usato nel modo sbagliato, aprendo il tuo sistema ad attacchi DoS.
Per risolvere questo problema, invece di considerare il punto come opzionale, dobbiamo trattarlo come richiesto (per separare le classi di caratteri ripetute) e invece rendere facoltativa l'intera parte decimale:
\d+(\.\d+)? /* Better. But... */
Adesso sta meglio. Abbiamo bisogno di un punto tra la prima sequenza di cifre e la seconda, ma c'è un difetto fatale: non possiamo abbinare .123perché ora è richiesta una cifra iniziale.
Questo in realtà è abbastanza facile da risolvere. Invece di rendere facoltativa la parte "decimale" del numero, dobbiamo considerarla come una sequenza di caratteri: 1 o più numeri che possono essere preceduti da un .che può essere preceduto da 0 o più numeri:
(\d*\.)?\d+
Ora aggiungiamo solo il segno:
[+-]?(\d*\.)?\d+
Ovviamente, quelle barre sono piuttosto fastidiose in Java, quindi possiamo sostituirle nelle nostre classi di caratteri in forma lunga:
[+-]?([0-9]*[.])?[0-9]+
Corrispondenza e convalida
Questo è emerso nei commenti un paio di volte, quindi aggiungo un addendum sulla corrispondenza rispetto alla convalida.
L'obiettivo della corrispondenza è trovare del contenuto all'interno dell'input ("l'ago in un pagliaio"). L'obiettivo della convalida è garantire che l'input sia nel formato previsto.
Le espressioni regolari, per loro natura, corrispondono solo al testo. Dato un input, troveranno del testo corrispondente o non lo faranno. Tuttavia, "agganciando" un'espressione all'inizio e alla fine dell'input con i tag di ancoraggio ( ^e $), possiamo garantire che non venga trovata alcuna corrispondenza a meno che l'intero input non corrisponda all'espressione, utilizzando effettivamente le espressioni regolari per convalidare .
L'espressione regolare descritta sopra ( [+-]?([0-9]*[.])?[0-9]+) corrisponderà a uno o più numeri all'interno di una stringa di destinazione. Quindi, dato l'input:
apple 1.34 pear 7.98 version 1.2.3.4
L'espressione regolare corrisponderà 1.34, 7.98, 1.2, .3e .4.
Per convalidare che un dato input sia un numero e nient'altro che un numero, "aggancia" l'espressione all'inizio e alla fine dell'input avvolgendola in anchor tag:
^[+-]?([0-9]*[.])?[0-9]+$
Questo troverà una corrispondenza solo se l'intero input è un numero in virgola mobile e non troverà una corrispondenza se l'input contiene caratteri aggiuntivi. Quindi, dato l'input 1.2, verrà trovata una corrispondenza, ma apple 1.2 pearnon verrà trovata nessuna corrispondenza.
Nota che alcuni motori di regex hanno una validate, isMatcho una funzione simile, che fa in sostanza quello che ho descritto automaticamente, tornando truese viene trovata una corrispondenza e falsese non viene trovata alcuna corrispondenza. Inoltre, tieni presente che alcuni motori ti consentono di impostare flag che cambiano la definizione di ^e $, facendo corrispondere l'inizio / fine di una riga piuttosto che l'inizio / fine dell'intero input. In genere non è l'impostazione predefinita, ma fai attenzione a queste bandiere.