Regex per rimuovere tutto (punto OR non numerico)


95

Ho bisogno di un testo come "joe ($ 3,004,50)" da filtrare fino a 3004,50 ma sono pessimo con regex e non riesco a trovare una soluzione adeguata. Quindi dovrebbero rimanere solo numeri e periodi, tutto il resto filtrato. Uso C # e VS.net 2008 framework 3.5

Risposte:


168

Questo dovrebbe farlo:

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

1
Di cosa joe.smith ($3,004.50)? La semplice rimozione delle classi di personaggi offensivi può andare abbastanza storto.
Matthew Gunn

2
Faccio una piccola correzione: Regex.Replace(s, "[^$0-9.]", "");vuoi lasciare il segno del dollaro.
bodacydo

36

La regex è:

[^0-9.]

Puoi memorizzare nella cache la regex:

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

quindi usa:

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

Tuttavia, tieni presente che alcune culture hanno convenzioni diverse per la scrittura di importi monetari, ad esempio: 3.004,50.


ATM troppo pigro per verificare, ma non è necessario sfuggire al file. ?
Andrew Anderson,

9
@Andrew: no, all'interno di una classe di caratteri, .non ha alcun significato speciale.
Bart Kiers

2

Per la risposta accettata, MatthewGunn solleva un punto valido in quanto tutte le cifre, le virgole e i punti dell'intera stringa saranno condensati insieme. Ciò eviterà che:

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

Sembra che la regex sopra abbia una parentesi extra. L'utilizzo (?:^|[^w.,])(\d[\d,.]+)(?=\W|$)corrisponderà anche a "h25" nella stringa "joe.smith25 ($ 3,004,50)"
Rivka

1

L'approccio alla rimozione dei personaggi offensivi è potenzialmente problematico. E se ce ne fosse un altro .nella stringa da qualche parte? Non verrà rimosso, anche se dovrebbe!

Rimuovendo le non cifre o i punti, la stringa joe.smith ($3,004.50)si trasformerebbe nel non analizzabile .3004.50.

Imho, è meglio abbinare uno schema specifico ed estrarlo usando un gruppo. Qualcosa di semplice sarebbe trovare tutte le virgole, le cifre e i punti contigui con regexp:

[\d,\.]+

Esempio di esecuzione di prova:

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"

Quindi, per ogni corrispondenza, rimuovi tutte le virgole e invialo al parser. Per gestire il caso di qualcosa di simile 12.323.344, potresti fare un altro controllo per vedere che una sottostringa corrispondente ne ha al massimo una ..


Questa regex corrisponde a tutto.
mindriot

Ora corrisponde a tutto tranne "".
mindriot

1
Il concetto che stai proponendo richiederebbe una regex complessa difficile da leggere ed eseguire il debug. Potrebbe essere meglio suddividerlo in passaggi con diverse espressioni regolari e condizionali. Potrei fornire una risposta (anche se scritto in Ruby perché non so c #.
mindriot

@mindriot Punto preso. L'ho cambiato in qualcosa di più trasparente.
Matthew Gunn

Per invio al parser, intendi Single.Parse()o Single.TryParse?
mindriot

1

Hai a che fare con una stringa: la stringa è un IEumerable<char>, quindi puoi usare LINQ:

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

Console.WriteLine(result);   // 3004.50
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.