Saltar al contenido

¿Cómo hace coincidir solo números romanos válidos con una expresión regular?

Solución:

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})$

Rompiéndolo M{0,4} especifica la sección de miles y básicamente la restringe entre 0 y 4000. Es 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ías usar algo como M* permitir alguna número (incluido el 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, 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 en 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 finalmente, (IX|IV|V?I{0,3}) es la sección de unidades, manejo 0 mediante 9 y también similar a las dos secciones anteriores (los números romanos, a pesar de su aparente rareza, siguen algunas reglas lógicas una vez que averiguas cuáles 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 desea esto (y su motor de expresiones regulares es lo suficientemente moderno), puede usar la búsqueda hacia atrás y hacia adelante positivas:

(?<=^)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).

En realidad, tu premisa es defectuosa. 990 ES “XM”, así como “CMXC”.

Los romanos estaban mucho menos preocupados por las “reglas” que su maestro de tercer grado. Mientras sumase, 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 el 1700. Hasta entonces, siempre que el lector pudiera entenderlo, era lo suficientemente bueno).

Solo para guardarlo aquí:

(^(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$)

Coincide con todos los números romanos. No le importan las cadenas vacías (requiere al menos una letra numérica romana). Debería funcionar en PCRE, Perl, Python y Ruby.

Demostración de Ruby en línea: http://rubular.com/r/KLPR1zq3Hj

Conversión en línea: http://www.onlineconversion.com/roman_numerals_advanced.htm

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *