Regex para eliminar todo (punto O no numérico)


95

Necesito que un texto como "joe ($ 3,004.50)" se filtre a 3004.50 pero soy terrible con las expresiones regulares y no puedo encontrar una solución adecuada. Por lo tanto, solo deben permanecer los números y los puntos, todo lo demás filtrado. Yo uso C # y VS.net 2008 framework 3.5

Respuestas:


168

Esto debería hacerlo:

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

1
¿Qué hay de joe.smith ($3,004.50)? Simplemente eliminar las clases de personajes ofensivos puede salir mal.
Matthew Gunn

2
Hago una pequeña corrección: Regex.Replace(s, "[^$0-9.]", "");quieres dejar el signo del dólar.
bodacydo

36

La expresión regular es:

[^0-9.]

Puede almacenar en caché la expresión regular:

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

luego usa:

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

Sin embargo, debe tener en cuenta que algunas culturas tienen diferentes convenciones para escribir cantidades monetarias, como: 3.004,50.


Cajero automático demasiado perezoso para verificar, pero no necesita escapar del. ?
Andrew Anderson

9
@Andrew: no, dentro de una clase de carácter, .no tiene un significado especial.
Bart Kiers

2

Para la respuesta aceptada, MatthewGunn plantea un punto válido en el sentido de que todos los dígitos, comas y puntos de toda la cadena se condensarán. Esto evitará que:

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

Parece que la expresión regular anterior tiene paréntesis extra. El uso (?:^|[^w.,])(\d[\d,.]+)(?=\W|$)también coincidirá con "h25" en la cadena "joe.smith25 ($ 3,004.50)"
Rivka

1

El enfoque de eliminar personajes ofensivos es potencialmente problemático. ¿Qué pasa si hay otro .en la cuerda en alguna parte? ¡No se eliminará, aunque debería!

Al eliminar los no dígitos o puntos, la cadena joe.smith ($3,004.50)se transformaría en lo que no se puede analizar .3004.50.

En mi humilde opinión, es mejor hacer coincidir un patrón específico y extraerlo usando un grupo. Algo simple sería encontrar todas las comas, dígitos y puntos contiguos con regexp:

[\d,\.]+

Ejecución de prueba de muestra:

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"

Luego, para cada coincidencia, elimine todas las comas y envíelo al analizador. Para manejar el caso de algo como 12.323.344, podría hacer otra verificación para ver que una subcadena coincidente tenga como máximo una ..


Esta expresión regular coincide con todo.
Mindriot

Ahora coincide con todo excepto "".
Mindriot

1
El concepto que propones requeriría una expresión regular compleja que sea difícil de leer y depurar. Puede ser mejor dividirlo en pasos con varias expresiones regulares y condicionales. Podría proporcionar una respuesta (aunque está escrito en Ruby, ya que no sé c #.)
mindriot

@mindriot Punto tomado. Lo cambié por algo más transparente.
Matthew Gunn

Por enviar al analizador, ¿te refieres a Single.Parse()o Single.TryParse?
Mindriot

1

Está tratando con una cadena, la cadena es una IEumerable<char>, por lo que puede usar LINQ:

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

Console.WriteLine(result);   // 3004.50
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.