Tümünü kaldırmak için normal ifade (sayısal olmayan VEYA nokta)


97

3004.50'ye kadar filtrelenecek "joe ($ 3.004.50)" gibi bir metne ihtiyacım var, ancak normal ifadede berbatım ve uygun bir çözüm bulamıyorum. Bu nedenle, yalnızca sayılar ve noktalar kalmalıdır - diğer her şey filtrelenir. C # ve VS.net 2008 framework 3.5 kullanıyorum

Yanıtlar:


174

Bunu yapmalı:

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

2
Peki ya joe.smith ($3,004.50)? Rahatsız edici karakter sınıflarını kaldırmak oldukça yanlış olabilir.
Matthew Gunn

2
Küçük bir düzeltme yapıyorum: Regex.Replace(s, "[^$0-9.]", "");Dolar işareti bırakmak istiyorsunuz.
bodacydo

37

Normal ifade:

[^0-9.]

Normal ifadeyi önbelleğe alabilirsiniz:

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

sonra kullan:

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

Bununla birlikte, bazı kültürlerin parasal miktarları yazmak için farklı kuralları olduğunu unutmamalısınız, örneğin: 3.004,50.


Doğrulamak için çok tembel ATM, ancak. ?
Andrew Anderson

9
@Andrew: hayır, bir karakter sınıfının .özel bir anlamı yoktur.
Bart Kiers

3

Bir dizeyle uğraşıyorsunuz - dizge bir IEumerable<char>, yani LINQ kullanabilirsiniz:

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

Console.WriteLine(result);   // 3004.50

2

Kabul edilen cevap için MatthewGunn, dizedeki tüm rakamların, virgüllerin ve noktaların birlikte yoğunlaştırılacağı konusunda geçerli bir noktayı ortaya koyuyor. Bu, şunları önleyecektir:

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

Görünüşe göre normal ifadede fazladan parantez var. Kullanımı (?:^|[^w.,])(\d[\d,.]+)(?=\W|$), "joe.smith25 ($ 3.004.50)" dizesindeki "h25" ile de eşleşecek
Rivka

1

Rahatsız edici karakterleri kaldırma yaklaşımı potansiyel olarak sorunludur. Ya .dizede bir yerlerde başka biri varsa ? Kaldırılması gerekse de kaldırılmayacak!

Basamaklı olmayanları veya noktaları kaldırarak, dize karşılaştırılamaz joe.smith ($3,004.50)hale gelir .3004.50.

Imho, belirli bir kalıbı eşleştirmek ve bir grup kullanarak çıkarmak daha iyidir. Basit bir şey, tüm bitişik virgülleri, rakamları ve dönemleri regexp ile bulmak olabilir:

[\d,\.]+

Örnek test çalıştırması:

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"

Ardından her eşleşme için tüm virgülleri kaldırın ve bunu ayrıştırıcıya gönderin. Böyle bir şeyi ele 12.323.344almak için, eşleşen bir alt dizenin en fazla bir alt dizeye sahip olup olmadığını görmek için başka bir kontrol yapabilirsiniz ..


Bu normal ifade her şeyle eşleşiyor.
mindriot

Artık dışındaki her şeyle eşleşiyor "".
mindriot

1
Önerdiğiniz kavram, okunması ve hata ayıklaması zor olan karmaşık bir normal ifade gerektirir. Bunu birkaç normal ifade ve koşullu adımlara bölmek daha iyi olabilir. Ben c # bilmiyorum olarak Ruby ile yazılmış rağmen (bir cevap verebilir.
mindriot

@mindriot Puan alındı. Daha şeffaf bir şeye değiştirdim.
Matthew Gunn

Ayrıştırıcıya gönder derken, ya Single.Parse()da Single.TryParsemı?
mindriot
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.