Espressione regolare per numero decimale

Devo convalidare un input da textbox e posso solo consentire input decimali come: X,XXX (solo una cifra prima del segno decimale e una precisione di 3).

Sto usando C # e provo questo ^[0-9]+(\.[0-9]{1,2})?$ ?

 ^[0-9]([.,][0-9]{1,3})?$ 

Permette:

 0 1 1.2 1.02 1.003 1.030 1,2 1,23 1,234 

MA NO:

 .1 ,1 12.1 12,1 1. 1, 1.2345 1,2345 

Esiste un approccio alternativo, che non ha problemi I18n (permettendo “,” o “.” Ma non entrambi): Decimal.TryParse .

Prova a convertire, ignorando il valore.

 bool IsDecimalFormat(string input) { Decimal dummy; return Decimal.TryParse(input, out dummy); } 

Questo è significativamente più veloce rispetto all’utilizzo di un’espressione regolare, vedi sotto.

(Il sovraccarico di Decimal.TryParse può essere utilizzato per un controllo più preciso.)


Risultati del test delle prestazioni: Decimal.TryParse: 0.10277ms, Regex: 0.49143ms

Codice ( PerformanceHelper.Run è un helper che esegue il delegato per il conteggio delle iterazioni passato e restituisce il TimeSpan medio.):

 using System; using System.Text.RegularExpressions; using DotNetUtils.Diagnostics; class Program { static private readonly string[] TestData = new string[] { "10.0", "10,0", "0.1", ".1", "Snafu", new string('x', 10000), new string('2', 10000), new string('0', 10000) }; static void Main(string[] args) { Action parser = () => { int n = TestData.Length; int count = 0; for (int i = 0; i < n; ++i) { decimal dummy; count += Decimal.TryParse(TestData[i], out dummy) ? 1 : 0; } }; Regex decimalRegex = new Regex(@"^[0-9]([\.\,][0-9]{1,3})?$"); Action regex = () => { int n = TestData.Length; int count = 0; for (int i = 0; i < n; ++i) { count += decimalRegex.IsMatch(TestData[i]) ? 1 : 0; } }; var paserTotal = 0.0; var regexTotal = 0.0; var runCount = 10; for (int run = 1; run <= runCount; ++run) { var parserTime = PerformanceHelper.Run(10000, parser); var regexTime = PerformanceHelper.Run(10000, regex); Console.WriteLine("Run #{2}: Decimal.TryParse: {0}ms, Regex: {1}ms", parserTime.TotalMilliseconds, regexTime.TotalMilliseconds, run); paserTotal += parserTime.TotalMilliseconds; regexTotal += regexTime.TotalMilliseconds; } Console.WriteLine("Overall averages: Decimal.TryParse: {0}ms, Regex: {1}ms", paserTotal/runCount, regexTotal/runCount); } } 
 \d{1}(\.\d{1,3})? Match a single digit 0..9 «\d{1}» Exactly 1 times «{1}» Match the regular expression below and capture its match into backreference number 1 «(\.\d{1,3})?» Between zero and one times, as many times as possible, giving back as needed (greedy) «?» Match the character “.” literally «\.» Match a single digit 0..9 «\d{1,3}» Between one and 3 times, as many times as possible, giving back as needed (greedy) «{1,3}» Created with RegexBuddy 

gli incontri:
1
1.2
1.23
1.234

In generale, ovvero cifre decimali illimitate:

^-?(([1-9]\d*)|0)(.0*[1-9](0*[1-9])*)?$

Ho appena trovato TryParse() ha un problema che rappresenta migliaia di separatori. Esempio in En-US, 10,36,00 è ok. Ho avuto uno scenario specifico in cui il separatore di migliaia non dovrebbe essere considerato e quindi regex \d(\.\d) si è rivelata la migliore scommessa. Ovviamente doveva mantenere la variabile decimale char per diverse localizzazioni.

In .NET, consiglio di creare dynamicmente l’espressione regolare con il separatore decimale del contesto culturale corrente:

 using System.Globalization; ... NumberFormatInfo nfi = NumberFormatInfo.CurrentInfo; Regex re = new Regex("^(?\\d+(" + Regex.Escape(nfi.CurrencyDecimalSeparator) + "\\d{1,2}))$"); 

Potresti voler sfruttare l’espressione regolare, consentendo separatori 1000er allo stesso modo del separatore decimale.

Mentre mi azzardo, TryParse in 3.5 ha NumberStyles: Il seguente codice dovrebbe anche fare il trucco senza Regex per ignorare migliaia di seperator.

 double.TryParse(length, NumberStyles.AllowDecimalPoint,CultureInfo.CurrentUICulture, out lengthD)) 

Non pertinente alla domanda originale, ma conferma che TryParse () è davvero una buona opzione.