Wyrażenie regularne, aby usunąć wszystko (nie numeryczne LUB kropka)


96

Potrzebuję odfiltrowania tekstu takiego jak „joe (3 004,50 USD)” do 3004,50, ale jestem okropny w przypadku wyrażenia regularnego i nie mogę znaleźć odpowiedniego rozwiązania. Więc tylko liczby i kropki powinny pozostać - wszystko inne jest filtrowane. Używam C # i VS.net 2008 framework 3.5

Odpowiedzi:


172

To powinno wystarczyć:

string s = "joe ($3,004.50)";
s = Regex.Replace(s, "[^0-9.]", "");

2
O co chodzi joe.smith ($3,004.50)? Zwykłe usuwanie obraźliwych klas postaci może się nie udać.
Matthew Gunn

2
Robię jedną małą poprawkę: Regex.Replace(s, "[^$0-9.]", "");chcesz zostawić znak dolara.
bodacydo

37

Wyrażenie regularne to:

[^0-9.]

Możesz buforować wyrażenie regularne:

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

następnie użyj:

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

Należy jednak pamiętać, że w niektórych kulturach obowiązują różne konwencje zapisywania kwot pieniężnych, na przykład: 3,004,50.


Zbyt leniwy bankomat do weryfikacji, ale nie musisz uciekać przed. ?
Andrew Anderson

9
@Andrew: nie, wewnątrz klasy postaci .nie ma specjalnego znaczenia.
Bart Kiers,

2

W przypadku zaakceptowanej odpowiedzi MatthewGunn podnosi prawidłowy punkt, w którym wszystkie cyfry, przecinki i kropki w całym ciągu zostaną skondensowane. Pozwoli to uniknąć tego:

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, ",", "");
}

Wygląda na to, że powyższe wyrażenie regularne ma dodatkowy nawias. Użycie (?:^|[^w.,])(\d[\d,.]+)(?=\W|$)spowoduje również dopasowanie „h25” do ciągu „joe.smith25 (3,004,50 $)”
Rivka

2

Masz do czynienia z stringiem - string to an IEumerable<char>, więc możesz użyć LINQ:

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

Console.WriteLine(result);   // 3004.50

1

Podejście do usuwania obraźliwych postaci jest potencjalnie problematyczne. A co, jeśli gdzieś .w ciągu jest inny ? Nie zostanie usunięty, ale powinien!

Usuwając joe.smith ($3,004.50)niecyfrowe lub kropki, ciąg przekształciłby się w nierozdzielny .3004.50.

Imho, lepiej jest dopasować określony wzorzec i wyodrębnić go za pomocą grupy. Prostym rozwiązaniem byłoby znalezienie wszystkich ciągłych przecinków, cyfr i kropek za pomocą wyrażenia regularnego:

[\d,\.]+

Przykładowy przebieg testowy:

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"

Następnie dla każdego dopasowania usuń wszystkie przecinki i wyślij to do parsera. Aby obsłużyć wielkość liter 12.323.344, możesz ponownie sprawdzić, czy pasujący podciąg ma co najwyżej jeden ..


To wyrażenie regularne pasuje do wszystkiego.
mindriot

Teraz pasuje do wszystkiego oprócz "".
mindriot

1
Koncepcja, którą proponujesz, wymagałaby złożonego wyrażenia regularnego, które jest trudne do odczytania i debugowania. Lepiej byłoby podzielić to na kroki z kilkoma wyrażeniami regularnymi i warunkami. Mógłbym udzielić odpowiedzi (chociaż napisane w Rubim, bo nie wiem c #.
mindriot

@mindriot Point zajęte. Zmieniłem to na coś bardziej przejrzystego.
Matthew Gunn

Wysyłając do parsera, masz na myśli albo Single.Parse()albo Single.TryParse?
mindriot
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.