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.