Puede usar la siguiente expresión regular para esto:
^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
Desglosándolo, M{0,4}
especifica la sección de miles y básicamente lo restringe entre 0
y 4000
. Es un relativamente simple:
0: <empty> matched by M{0}
1000: M matched by M{1}
2000: MM matched by M{2}
3000: MMM matched by M{3}
4000: MMMM matched by M{4}
Por supuesto, podría usar algo como M*
permitir cualquier número (incluido cero) de miles, si desea permitir números más grandes.
El siguiente es (CM|CD|D?C{0,3})
, un poco más complejo, esto es para la sección de cientos y cubre todas las posibilidades:
0: <empty> matched by D?C{0} (with D not there)
100: C matched by D?C{1} (with D not there)
200: CC matched by D?C{2} (with D not there)
300: CCC matched by D?C{3} (with D not there)
400: CD matched by CD
500: D matched by D?C{0} (with D there)
600: DC matched by D?C{1} (with D there)
700: DCC matched by D?C{2} (with D there)
800: DCCC matched by D?C{3} (with D there)
900: CM matched by CM
En tercer lugar, (XC|XL|L?X{0,3})
sigue las mismas reglas que la sección anterior pero para el lugar de las decenas:
0: <empty> matched by L?X{0} (with L not there)
10: X matched by L?X{1} (with L not there)
20: XX matched by L?X{2} (with L not there)
30: XXX matched by L?X{3} (with L not there)
40: XL matched by XL
50: L matched by L?X{0} (with L there)
60: LX matched by L?X{1} (with L there)
70: LXX matched by L?X{2} (with L there)
80: LXXX matched by L?X{3} (with L there)
90: XC matched by XC
Y, por último, (IX|IV|V?I{0,3})
es la sección de unidades, la manipulación 0
a través 9
y también similar a las dos secciones anteriores (números romanos, a pesar de su aparente rareza, siguen algunas reglas lógicas vez que averiguar lo que son):
0: <empty> matched by V?I{0} (with V not there)
1: I matched by V?I{1} (with V not there)
2: II matched by V?I{2} (with V not there)
3: III matched by V?I{3} (with V not there)
4: IV matched by IV
5: V matched by V?I{0} (with V there)
6: VI matched by V?I{1} (with V there)
7: VII matched by V?I{2} (with V there)
8: VIII matched by V?I{3} (with V there)
9: IX matched by IX
Solo tenga en cuenta que esa expresión regular también coincidirá con una cadena vacía. Si no quiere esto (y su motor regex es lo suficientemente moderno), puede usar una mirada positiva hacia atrás y hacia adelante:
(?<=^)M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})(?=$)
(la otra alternativa es simplemente verificar que la longitud no sea cero de antemano).
MMMM
era la forma correcta. La representación overbar llegó mucho después de que el imperio central se desmoronara./^M{0,3}(?:C[MD]|D?C{0,3})(?:X[CL]|L?X{0,3})(?:I[XV]|V?I{0,3})$/i
En realidad, tu premisa es defectuosa. 990 IS "XM", así como "CMXC".
Los romanos estaban mucho menos preocupados por las "reglas" que su maestra de tercer grado. Mientras se acumulara, estaba bien. Por lo tanto, "IIII" fue tan bueno como "IV" para 4. Y "IIM" fue completamente genial para 998.
(Si tiene problemas para lidiar con eso ... Recuerde que la ortografía en inglés no se formalizó hasta la década de 1700. Hasta entonces, siempre que el lector pudiera entenderlo, era lo suficientemente bueno).
fuente
Solo para guardarlo aquí:
Coincide con todos los números romanos. No le importan las cadenas vacías (requiere al menos una letra de número romano). Debería funcionar en PCRE, Perl, Python y Ruby.
Demostración en línea de Ruby: http://rubular.com/r/KLPR1zq3Hj
Conversión en línea: http://www.onlineconversion.com/roman_numerals_advanced.htm
fuente
Para evitar hacer coincidir la cadena vacía, deberá repetir el patrón cuatro veces y reemplazar cada uno
0
por uno1
, y tener en cuentaV
,L
yD
:En este caso (debido a que este patrón usa
^
y$
) sería mejor que primero verifique si hay líneas vacías y no se moleste en combinarlas. Si está utilizando límites de palabras, entonces no tiene un problema porque no existe una palabra vacía. (Al menos la expresión regular no define uno; no empieces a filosofar, ¡estoy siendo pragmático aquí!)En mi caso particular (del mundo real), necesitaba números coincidentes en las terminaciones de palabras y no encontré otra forma de evitarlo. Necesitaba borrar los números de las notas al pie de página de mi documento de texto plano, donde se había convertido texto como "el cl del Mar Rojo y el cli de la Gran Barrera de Coral "
the Red Seacl and the Great Barrier Reefcli
. Pero todavía tenía problemas con palabras válidas comoTahiti
yfantastic
se eliminan enTahit
yfantasti
.fuente
M
oC
, oL
, por lo que, ¿tiene este tipo de expresiones regulares simplificadas?(X{1,3}(IX|IV|V?I{0,3})|X{0,3}(IX|I?V|V?I{1,3}))
Afortunadamente, el rango de números está limitado a 1..3999 o más o menos. Por lo tanto, puede construir la comida de piezas regex.
Cada una de esas partes se ocupará de los caprichos de la notación romana. Por ejemplo, usando la notación Perl:
Repetir y armar.
Agregado :
<opt-hundreds-part>
se puede comprimir aún más:Dado que la cláusula 'D? C {0,3}' no puede coincidir con nada, no hay necesidad del signo de interrogación. Y, lo más probable, los paréntesis deben ser del tipo sin captura, en Perl:
Por supuesto, también debería ser insensible a mayúsculas y minúsculas.
También puede ampliar esto para manejar las opciones mencionadas por James Curran (para permitir XM o IM para 990 o 999, y CCCC para 400, etc.).
fuente
thousands hundreds tens units
, es fácil crear un FSM que calcule y valide los números romanos dadosPara las personas que realmente quieren entender la lógica, eche un vistazo a una explicación paso a paso en 3 páginas sobre diveintopython .
La única diferencia con la solución original (que tenía
M{0,4}
) es porque descubrí que 'MMMM' no es un número romano válido (los romanos antiguos probablemente no hayan pensado en ese gran número y estarán en desacuerdo conmigo). Si eres de los romanos viejos en desacuerdo, perdóname y usa la versión {0,4}.fuente
Estoy respondiendo esta pregunta Expresión regular en Python para números romanos aquí
porque se marcó como un duplicado exacto de esta pregunta.
Puede ser similar en nombre, pero esta es una pregunta / problema específico de expresiones regulares
como se puede ver en esta respuesta a esa pregunta.
Los elementos que se buscan pueden combinarse en una sola alternancia y luego
encerrarse dentro de un grupo de captura que se colocará en una lista con la función findall ()
.
Se hace así:
Las modificaciones de expresiones regulares para factorizar y capturar solo los números son las siguientes:
fuente
Como Jeremy y Pax señalaron anteriormente ... '^ M {0,4} (CM | CD | D? C {0,3}) (XC | XL | L? X {0,3}) (IX | IV | V? I {0,3}) $ 'debería ser la solución que buscas ...
La URL específica que debería haberse adjuntado (en mi humilde opinión) es http://thehazeltree.org/diveintopython/7.html
El ejemplo 7.8 es la forma corta usando {n, m}
fuente
En mi caso, estaba tratando de encontrar y reemplazar todas las apariciones de números romanos por una palabra dentro del texto, por lo que no pude usar el inicio y el final de las líneas. Entonces, la solución @paxdiablo encontró muchas coincidencias de longitud cero. Terminé con la siguiente expresión:
Mi código final de Python fue así:
Salida:
fuente
Steven Levithan usa esta expresión regular en su publicación que valida los números romanos antes de "desromanizar" el valor:
fuente
He visto múltiples respuestas que no cubren cadenas vacías o usan lookaheads para resolver esto. Y quiero agregar una nueva respuesta que cubra cadenas vacías y no use anticipación. La expresión regular es la siguiente:
^(I[VX]|VI{0,3}|I{1,3})|((X[LC]|LX{0,3}|X{1,3})(I[VX]|V?I{0,3}))|((C[DM]|DC{0,3}|C{1,3})(X[LC]|L?X{0,3})(I[VX]|V?I{0,3}))|(M+(C[DM]|D?C{0,3})(X[LC]|L?X{0,3})(I[VX]|V?I{0,3}))$
Estoy permitiendo infinito
M
,M+
pero, por supuesto, alguien podría cambiarM{1,4}
para permitir solo 1 o 4 si lo desea.A continuación se muestra una visualización que ayuda a comprender lo que está haciendo, precedida por dos demostraciones en línea:
Demo de Debuggex
Regex 101 Demo
fuente
Esto funciona en los motores de expresiones regulares Java y PCRE y ahora debería funcionar en el último JavaScript, pero puede no funcionar en todos los contextos.
(?<![A-Z])(M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3}))(?![A-Z])
La primera parte es la atroz mirada negativa detrás. Pero, para fines lógicos, es el más fácil de entender. Básicamente, el primero
(?<!)
dice que no coinciden con el medio([MATCH])
si hay letras que vienen antes del medio([MATCH])
y el último(?!)
dice que no coinciden con el medio([MATCH])
si hay letras que vienen después.El medio
([MATCH])
es solo la expresión regular más utilizada para hacer coincidir la secuencia de números romanos. Pero ahora, no desea hacer coincidir eso si hay letras alrededor.Ver por ti mismo. https://regexr.com/4vce5
fuente
El problema de la solución de Jeremy y Pax es que también coincide con "nada".
La siguiente expresión regular espera al menos un número romano:
fuente
|
puede coincidir con una cadena vacía y todos los números romanos válidos, por lo que el lado derecho es completamente redundante. y sí, todavía coincide con una cadena vacía.Escribiría funciones en mi trabajo por mí. Aquí hay dos funciones de números romanos en PowerShell.
fuente