Regex, um alle zu entfernen (nicht numerische ODER-Periode)

92

Ich muss Text wie "joe ($ 3,004.50)" auf 3004.50 filtern, aber ich bin schrecklich bei Regex und kann keine geeignete Lösung finden. Es sollten also nur Zahlen und Punkte bleiben - alles andere gefiltert. Ich verwende C # und VS.net 2008 Framework 3.5

Bereit Cent
quelle

Antworten:

166

Dies sollte es tun:

string s = "joe ($3,004.50)";
s = Regex.Replace(s, "[^0-9.]", "");
josephj1989
quelle
1
Was ist mit joe.smith ($3,004.50)? Das einfache Entfernen von beleidigenden Zeichenklassen kann völlig schief gehen.
Matthew Gunn
2
Ich mache eine kleine Korrektur: Regex.Replace(s, "[^$0-9.]", "");Sie möchten das Dollarzeichen hinterlassen.
Bodacydo
35

Der reguläre Ausdruck ist:

[^0-9.]

Sie können den regulären Ausdruck zwischenspeichern:

Regex not_num_period = new Regex("[^0-9.]")

dann benutze:

string result = not_num_period.Replace("joe ($3,004.50)", "");

Beachten Sie jedoch, dass einige Kulturen unterschiedliche Konventionen für das Schreiben von Geldbeträgen haben, z. B.: 3.004,50.

Matthew Flaschen
quelle
Zu fauler Geldautomat, um dies zu überprüfen, aber Sie müssen dem nicht entkommen. ?
Andrew Anderson
7
@ Andrew: Nein, innerhalb einer Zeichenklasse .hat keine besondere Bedeutung.
Bart Kiers
2

Für die akzeptierte Antwort wirft MatthewGunn einen gültigen Punkt insofern auf, als alle Ziffern, Kommas und Punkte in der gesamten Zeichenfolge zusammengefasst werden. Dadurch wird Folgendes vermieden:

string s = "joe.smith ($3,004.50)";
Regex r = new Regex(@"(?:^|[^w.,])(\d[\d,.]+)(?=\W|$)/)");
Match m = r.match(s);
string v = null;
if (m.Success) {
  v = m.Groups[1].Value;
  v = Regex.Replace(v, ",", "");
}
Mindriot
quelle
Scheint über Regex hat zusätzliche Klammern. Die Verwendung entspricht (?:^|[^w.,])(\d[\d,.]+)(?=\W|$)auch "h25" in der Zeichenfolge "joe.smith25 ($ 3,004.50)"
Rivka
1

Der Ansatz, beleidigende Zeichen zu entfernen, ist möglicherweise problematisch. Was ist, wenn .irgendwo ein anderer in der Zeichenfolge ist? Es wird nicht entfernt, obwohl es sollte!

Wenn Sie keine Ziffern oder joe.smith ($3,004.50)Punkte entfernen, wird die Zeichenfolge in die nicht analysierbare Zeichenfolge umgewandelt .3004.50.

Imho, es ist besser, ein bestimmtes Muster abzugleichen und es mit einer Gruppe zu extrahieren. Etwas Einfaches wäre, alle zusammenhängenden Kommas, Ziffern und Punkte mit regulärem Ausdruck zu finden:

[\d,\.]+

Beispieltestlauf:

Pattern understood as:
[\d,\.]+
Enter string to check if matches pattern
>  a2.3 fjdfadfj34  34j3424  2,300 adsfa    
Group 0 match: "2.3"
Group 0 match: "34"
Group 0 match: "34"
Group 0 match: "3424"
Group 0 match: "2,300"

Entfernen Sie dann für jede Übereinstimmung alle Kommas und senden Sie diese an den Parser. Um den Fall von so etwas zu behandeln 12.323.344, können Sie eine weitere Überprüfung durchführen, um festzustellen, ob ein passender Teilstring höchstens einen hat ..

Matthew Gunn
quelle
Diese Regex passt zu allem.
Mindriot
Es passt jetzt alles außer "".
Mindriot
1
Das von Ihnen vorgeschlagene Konzept würde einen komplexen regulären Ausdruck erfordern, der schwer zu lesen und zu debuggen ist. Es kann besser sein, es in Schritte mit mehreren regulären Ausdrücken und Bedingungen zu unterteilen. Ich könnte eine Antwort geben (obwohl in Ruby geschrieben, da ich c # nicht kenne.
mindriot
@mindriot Punkt genommen. Ich habe es in etwas Transparenteres geändert.
Matthew Gunn
Mit "an Parser senden" meinen Sie entweder Single.Parse()oder Single.TryParse?
Mindriot
1

Sie haben es mit einer Zeichenfolge zu tun - Zeichenfolge ist eine IEumerable<char>, sodass Sie LINQ verwenden können:

var input = "joe ($3,004.50)";
var result = String.Join("", input.Where(c => Char.IsDigit(c) || c == '.'));

Console.WriteLine(result);   // 3004.50
wb
quelle