Estoy tratando de ubicar y reemplazar todos los números en un cuerpo de texto. Encontré algunos ejemplos de expresiones regulares, que casi resuelven el problema, pero ninguno es perfecto todavía. El problema que tengo es que los números de mi texto pueden tener o no decimales y comas. Por ejemplo:
"El zorro de 5000 libras saltó una valla de 99,999.99998713 pies".
La expresión regular debería devolver " 5000
" y " 99,999.99998713
". Ejemplos He encontrado que los números de la coma están divididos o están limitados a dos lugares decimales. Estoy empezando a comprender las expresiones regulares lo suficiente como para ver por qué algunos ejemplos están limitados a dos lugares decimales, pero aún no he aprendido cómo superarlo y también incluir la coma para obtener la secuencia completa.
Aquí está mi última versión:
[0-9]+(\.[0-9][0-9]?)?
Que devuelve, " 5000
", " 99,99
", " 9.99
" y " 998713
" para el texto anterior.
.,.,.
o9,9,9,9
o9,9.99.9
. Estas expresiones regulares no requerirán que los números estén en el formato adecuado y, en el peor de los casos, tratarán la puntuación como números. Hay algunos ajustes opcionales posibles (por ejemplo, si permitir ceros iniciales y finales), pero algunas de las respuestas que estoy viendo son totalmente incorrectas. Realmente no me gusta votar negativamente, especialmente en los intentos honestos, pero siento que las respuestas aquí necesitan una limpieza. Esta es una pregunta común y definitivamente se volverá a hacer.Respuestas:
EDITAR: Dado que esto ha obtenido muchas visitas, permítanme comenzar dándoles a todos lo que buscaron en Google:
Ahora que eso está fuera del camino, la mayor parte de lo siguiente es un comentario sobre lo compleja que puede llegar a ser la expresión regular si intenta ser inteligente con ella, y por qué debería buscar alternativas. Lea bajo su propio riesgo.
Esta es una tarea muy común, pero todas las respuestas que veo aquí hasta ahora aceptará entradas que no coinciden con el formato de número, como por ejemplo
,111
,9,9,9
o incluso.,,.
. Eso es bastante simple de solucionar, incluso si los números están incrustados en otro texto. En mi humilde opinión cualquier cosa que no puede cargar 1,234.56 y 1234- y sólo esos números salida privado deabc22 1,234.56 9.9.9.9 def 1234
una respuesta incorrecta.En primer lugar, si no necesita hacer todo esto en una expresión regular, no lo haga. Una sola expresión regular para dos formatos de números diferentes es difícil de mantener incluso cuando no están incrustados en otro texto. Lo que realmente debe hacer es dividir todo en espacios en blanco, luego ejecutar dos o tres expresiones regulares más pequeñas en los resultados. Si esa no es una opción para ti, sigue leyendo.
Patrón básico
Teniendo en cuenta los ejemplos que ha dado, aquí hay una expresión regular simple que permite prácticamente cualquier
0000
formato entero o decimal y bloquea todo lo demás:Aquí hay uno que requiere
0,000
formato:Ponlos juntos y las comas se vuelven opcionales siempre que sean consistentes:
Números incrustados
Los patrones anteriores requieren que toda la entrada sea un número. Está buscando números incrustados en el texto, por lo que debe aflojar esa parte. Por otro lado, no quiere que vea
catch22
y crea que ha encontrado el número 22. Si está usando algo con soporte de búsqueda hacia atrás (como .NET), esto es bastante fácil: reemplace^
con(?<!\S)
y$
con(?!\S)
y estará bien ir:Si está trabajando con JavaScript o Ruby o algo así, las cosas comienzan a parecer más complejas:
Tendrás que usar grupos de captura; No puedo pensar en una alternativa sin el apoyo de mirar atrás. Los números que desea estarán en el Grupo 1 (asumiendo que todo el partido es el Grupo 0).
Validación y reglas más complejas
Creo que eso cubre tu pregunta, así que si eso es todo lo que necesitas, deja de leer ahora. Si quieres ser más elegante, las cosas se vuelven muy complejas muy rápidamente. Dependiendo de su situación, es posible que desee bloquear alguno o todos los siguientes:
Solo por el placer de hacerlo, supongamos que desea bloquear los primeros 3, pero permita el último. ¿Qué deberías hacer? Le diré lo que debe hacer, debe usar una expresión regular diferente para cada regla y reducir progresivamente sus coincidencias. Pero por el bien del desafío, así es como lo haces todo en un patrón gigante:
Y esto es lo que significa:
Probado aquí: http://rextester.com/YPG96786
Esto permitirá cosas como:
Bloqueará cosas como:
Hay varias formas de hacer esta expresión regular más simple y más corta, pero comprenda que cambiar el patrón aflojará lo que se considera un número.
Dado que muchos motores de expresiones regulares (por ejemplo, JavaScript y Ruby) no admiten la búsqueda hacia atrás negativa, la única forma de hacerlo correctamente es con grupos de captura:
Los números que está buscando estarán en el grupo de captura 1.
Probado aquí: http://rubular.com/r/3HCSkndzhT
Una nota final
Obviamente, esta es una expresión regular masiva, complicada y casi ilegible. Disfruté del desafío, pero debería considerar si realmente desea utilizarlo en un entorno de producción. En lugar de intentar hacer todo en un solo paso, puede hacerlo en dos: una expresión regular para detectar cualquier cosa que pueda ser un número, luego otra para eliminar lo que no sea un número. O puede hacer un procesamiento básico y luego usar las funciones de análisis numérico integradas de su idioma. Tu elección.
fuente
Hace algunos días, trabajé en el problema de eliminar los ceros finales de la cadena de un número .
En la continuidad de ese problema, encuentro este interesante porque amplía el problema a números que comprenden comas.
Tomé el patrón de expresiones regulares que había escrito en el problema anterior en el que trabajé y lo mejoré para que pueda tratar los números con comas como respuesta a este problema.
Me he dejado llevar por mi entusiasmo y mi gusto por las expresiones regulares. No sé si el resultado se ajusta exactamente a la necesidad expresada por Michael Prescott. Me interesaría conocer los puntos que sobran o faltan en mi expresión regular, y corregirlo para que sea más adecuado para ti.
Ahora, después de una larga sesión de trabajo en esta expresión regular, tengo una especie de peso en el cerebro, así que no estoy lo suficientemente fresco para dar muchas explicaciones. Si los puntos son oscuros, y si alguien puede llegar a estar lo suficientemente interesado, por favor, pregúnteme.
La expresión regular está construida para que pueda detectar los números expresados en notación científica 2E10 o incluso 5,22,454.12E-00.0478 , eliminando ceros innecesarios en las dos partes de dichos números también. Si un exponente es igual a cero, el número se modifica para que no haya más exponente.
Puse alguna verificación en el patrón para que algunos casos particulares no coincidan, por ejemplo, '12 ..57 ' no coincidirá. Pero en ', 111' la cadena '111' coincide porque la coma anterior se considera una coma que no está en un número sino en una coma de oración.
Creo que debería mejorarse la gestión de las comas, porque me parece que solo hay 2 dígitos entre comas en la numeración india. No será difícil de corregir, supongo
A continuación, se muestra un código que demuestra cómo funciona mi expresión regular. Hay dos funciones, según se quiera transformar los números '.1245' en '0.1245' o no. No me sorprendería que en ciertos casos de cadenas de números persistan errores o coincidencias no deseadas o no coincidentes; entonces me gustaría conocer estos casos para comprender y corregir la deficiencia.
Pido disculpas por este código escrito en Python, pero las expresiones regulares son trans-idioma y creo que todos serán capaces de entender el patrón de reex
resultado
fuente
La expresión regular a continuación coincidirá con ambos números de su ejemplo.
Devolverá 5000 y 99,999.99998713, coincidiendo con sus requisitos.
fuente
this,that
.\b\d[\d,.]+\b
9....9
o1,,,,X
(aunque la X no se incluirá en el partido).\b\d[\d,.]*\b
está lo suficientemente cerca como para que si editas tu respuesta, eliminaré el -1. Sin embargo, debería ser un * en lugar de un +;\b\d[\d,.]+\b
no permitirá números de un solo dígito.Tomándose una cierta libertad con los requisitos, está buscando
Pero tenga en cuenta que esto coincidirá, por ejemplo, con 11,11,1
fuente
\d+([\d,]?\d)*(\.\d+)?
lugar de\d+(,\d+)*(\.\d+)?
? Creo que darían coincidencias equivalentes, aunque los grupos de captura serían diferentes.Esto supone que siempre hay al menos un dígito antes o después de cualquier coma o decimal y también supone que hay como máximo un decimal y que todas las comas preceden al decimal.
fuente
999999,9,9,9,9
.(,\d+)
a(,\d\d\d)
, supongo.Esta expresión regular:
Coincidió con todos los números de la cadena:
1 1.0 0.1 1.001 1,000 1,000,000 1000.1 1,000.1 1,323,444,000 1,999 1,222,455,666.0 1,244
fuente
Aquí hay una expresión regular:
que acepta números:
123456789
,123.123
123 456 789
,123 456 789.100
,123,456
,3,232,300,000.00
Pruebas: http://regexr.com/3h1a2
fuente
Aquí hay otra construcción que comienza con el formato de número más simple y luego, de una manera no superpuesta, agrega progresivamente formatos de número más complejos:
Regep de Java:
Como una cadena de Java (tenga en cuenta el \ adicional necesario para escapar a \ y. Desde \ y. Tienen un significado especial en una expresión regular cuando están solos):
Explicación:
Esta expresión regular tiene la forma A | B | C | D | E | F donde A, B, C, D, E, F son en sí mismas expresiones regulares que no se superponen. En general, me resulta más fácil comenzar con las coincidencias más simples posibles, A. Si A falla las coincidencias que desea, cree una B que sea una modificación menor de A e incluya un poco más de lo que desea. Luego, basado en B, cree una C que capture más, etc. También me resulta más fácil crear expresiones regulares que no se superponen; Es más fácil entender una expresión regular con 20 expresiones regulares simples no superpuestas conectadas con OR en lugar de unas pocas expresiones regulares con coincidencias más complejas. Pero, ¡cada uno a lo suyo!
A es (\ d) y coincide exactamente con uno de 0,1,2,3,4,5,6,7,8,9 que no puede ser más simple.
B es ([1-9] \ d +) y solo coincide con números con 2 o más dígitos, el primero excluyendo 0. B coincide exactamente con uno de 10,11,12, ... B no se superpone a A, pero es una pequeña modificación de A.
C es (. \ D +) y solo coincide con un decimal seguido de uno o más dígitos. C coincide exactamente con uno de .0 .1 .2 .3 .4 .5 .6 .7 .8 .9 .00 .01 .02 .... .23000 ... C permite arrastrar eros a la derecha, lo que prefiero: si se trata de datos de medición, el número de ceros finales indica el nivel de precisión. Si no quiere los ceros finales a la derecha, cambie (. \ D +) a (. \ D * [1-9]) pero esto también excluye .0 que creo que debería estar permitido. C también es una pequeña modificación de A.
D es (\ d. \ D *) que es A más decimales con ceros a la derecha. D solo coincide con un solo dígito, seguido de un decimal, seguido de cero o más dígitos. D coincide con 0. 0.0 0.1 0.2 .... 0.01000 ... 9. 9.0 9.1..0.0230000 .... 9.9999999999 ... Si desea excluir "0." luego cambie D a (\ d. \ d +). Si desea excluir los ceros finales a la derecha, cambie D a (\ d. \ D * [1-9]) pero esto excluye 2.0, que creo que debería incluirse. D no se superpone a A, B o C.
E es ([1-9] \ d +. \ D *) que es B más decimales con ceros a la derecha. Si desea excluir "13.", por ejemplo, cambie E a ([1-9] \ d +. \ D +). E no se superpone a A, B, C o D. E coincide con 10. 10.0 10.0100 .... 99.9999999999 ... Los ceros finales se pueden manejar como en 4. y 5.
F es ([1-9] \ d {0,2} (, \ d {3}) + (. \ D *)?) Y solo coincide con números con comas y posiblemente decimales, permitiendo ceros finales a la derecha. El primer grupo ([1-9] \ d {0,2}) coincide con un dígito distinto de cero seguido de cero, uno o dos dígitos más. El segundo grupo (, \ d {3}) + coincide con un grupo de 4 caracteres (una coma seguida de exactamente tres dígitos) y este grupo puede coincidir una o más veces (¡sin coincidencias significa que no hay comas!). Finalmente, (. \ D *)? coincide con nada, o coincide. por sí mismo o coincide con un decimal. seguido de cualquier número de dígitos, posiblemente ninguno. Nuevamente, para excluir cosas como "1,111.", Cambie (. \ D *) a (. \ D +). Los ceros finales se pueden manejar como en 4. o 5. F no se superpone a A, B, C, D o E. No podría pensar en una expresión regular más fácil para F.
Avíseme si está interesado y puedo editar arriba para manejar los ceros finales a la derecha como desee.
Esto es lo que coincide con regexp y lo que no:
fuente
\ b -------> límite de palabra
\ d + ------> uno o dígito
, --------> que contiene comas,
P.ej:
sddsgg 70.000 sdsfdsf fdgfdg70,00
sfsfsd 5,44,4343 5.7788,44 555
Coincidirá:
70,
5,
44,
, 44
fuente
Esto coincidiría con cualquier número pequeño o grande como sigue con o sin coma
o
fuente