2010-11-26 4 views
9

Je construis une application .Net et je dois enlever tout caractère non-décimal d'une chaîne (à l'exclusion du premier '.'). Essentiellement, je nettoie l'entrée de l'utilisateur pour forcer un résultat réel. Jusqu'à présent, j'utilisais des outils RegEx en ligne pour essayer de réaliser ceci en un seul passage, mais je ne vais pas très loin.Trouver tout sauf la première occurrence d'un caractère avec REGEX

Je souhaite d'y arriver:

asd123.asd123.123.123 = 123.123123123 

Malheureusement, je n'ai réussi à arriver au stade où

asd123.asd123.123.123 = 123.123.123.123 

en utilisant ce code.

System.Text.RegularExpressions.Regex.Replace(str, "[^\.|\d]*", "") 

Mais je suis bloqué en essayant d'enlever tout sauf le premier point décimal.

Cela peut-il être fait en un seul passage?
Y a-t-il un meilleur moyen?

+0

's/[.]/\ X {DEADBEEF} /; s/[^. \ d \ x {DEADBEEF}] // g; s/\ x {DEADBEEF} /./; ' – tchrist

Répondre

6

Cela peut se faire en une seule expression régulière, au moins dans .NET qui supporte répétition à l'infini à l'intérieur lookbehind assertions:

resultString = Regex.Replace(subjectString, @"(?<!^[^.]*)\.|[^\d.]", ""); 

Explication:

(?<!^[^.]*) # Either match (as long as there is at least one dot before it) 
\.   # a dot 
|   # or 
[^\d.]  # any characters except digits or dots. 

(?<!^[^.]*) signifie: Assert qu'il est impossible de faire correspondre une chaîne qui commence au début de la chaîne d'entrée et se compose uniquement de caractères autres que les points. Cette condition est vraie pour tous les points suivant le premier.

+1

Merci, cet exemple m'a appris des choses que je n'ai jamais connues sur regex. – Mike

+0

merci, j'ai appris quelque chose de nouveau aussi! Je n'ai pas été capable de comprendre l'exemple avant de lire le lien vers les assertions lookbehind!Cela m'a aidé aussi! –

0

Tout d'abord, l'expression rationnelle que vous utilisez actuellement laissera une | caractères intacts. Vous avez seulement besoin [^.\d]* depuis . n'a pas de signification particulière dans []

Après cette opération de remplacement, vous pouvez essayer quelque chose comme ceci:

Replace(str, "([\d]+\.[\d]+)[^\d].*", "\1"); 

Mais vous auriez besoin que cela s'il y a un . du tout dans la nombre.

Espérons que cela aide.

+0

Merci pour la fixation de la première partie. Selon http://regexpal.com/ votre deuxième regex correspondrait à tous 123.123.123.123 est-ce que l'effet désiré? Je n'ai pas vu "\ 1" utilisé avant. – Mike

+0

Hmm, la deuxième regex devrait correspondre à tout cela, puis le remplacer par \ 1 (qui devrait être le premier sous-modèle, la partie dans '()') ne laissant que 123.123 - sauf si .NET utilise un système regex différent de habitué! –

2

Je pense que ça ira mieux sans expressions régulières.

string str = "asd123.asd123.123.123"; 
StringBuilder sb = new StringBuilder(); 
bool dotFound = false; 
foreach (var character in str) 
{ 
    if (Char.IsDigit(character)) 
     sb.Append(character); 
    else if (character == '.') 
     if (!dotFound) 
     { 
      dotFound = true; 
      sb.Append(character); 
     } 
} 
Console.WriteLine(sb.ToString()); 
+0

Merci, j'apprécie cette réponse. Je n'avais même pas pensé à tenter ce genre de logique. J'aimerais pouvoir accepter 2 réponses. – Mike

Questions connexes