Vous pouvez utiliser l'expression régulière suivante pour cela:
^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
Le décomposer, M{0,4}
spécifie la section des milliers et la restreint essentiellement entre 0
et 4000
. C'est un moyen relativement 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}
Vous pouvez, bien sûr, utiliser quelque chose comme M*
autoriser n'importe quel nombre (y compris zéro) de milliers, si vous voulez autoriser des nombres plus grands.
Ensuite (CM|CD|D?C{0,3})
, un peu plus complexe, c'est pour la section des centaines et couvre toutes les possibilités:
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
Troisièmement, (XC|XL|L?X{0,3})
suit les mêmes règles que la section précédente mais pour la place des dizaines:
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
Et, enfin, (IX|IV|V?I{0,3})
la section des unités, traitant à 0
travers 9
et également similaire aux deux sections précédentes (les chiffres romains, malgré leur apparente bizarrerie, suivent certaines règles logiques une fois que vous avez compris ce qu'ils sont):
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
Gardez simplement à l'esprit que cette expression régulière correspondra également à une chaîne vide. Si vous ne le souhaitez pas (et que votre moteur regex est suffisamment moderne), vous pouvez utiliser une anticipation et une anticipation positives:
(?<=^)M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})(?=$)
(l'autre alternative étant simplement de vérifier au préalable que la longueur n'est pas nulle).
MMMM
c'était la bonne voie. La représentation overbar est venue longtemps après la chute de l'empire central./^M{0,3}(?:C[MD]|D?C{0,3})(?:X[CL]|L?X{0,3})(?:I[XV]|V?I{0,3})$/i
En fait, votre prémisse est imparfaite. 990 EST "XM", ainsi que "CMXC".
Les Romains étaient beaucoup moins préoccupés par les «règles» que votre professeur de troisième année. Tant que cela s'additionnait, tout allait bien. Donc "IIII" était aussi bon que "IV" pour 4. Et "IIM" était complètement cool pour 998.
(Si vous avez du mal à gérer cela ... Rappelez-vous que les orthographes anglaises n'étaient pas formalisées avant les années 1700. Jusque-là, tant que le lecteur pouvait le comprendre, c'était assez bon).
la source
Juste pour le sauvegarder ici:
Correspond à tous les chiffres romains. Ne se soucie pas des chaînes vides (nécessite au moins une lettre en chiffres romains). Devrait fonctionner en PCRE, Perl, Python et Ruby.
Démo Ruby en ligne: http://rubular.com/r/KLPR1zq3Hj
Conversion en ligne: http://www.onlineconversion.com/roman_numerals_advanced.htm
la source
Pour éviter de faire correspondre la chaîne vide, vous devrez répéter le modèle quatre fois et remplacer chacun
0
par un1
tour à tour, et prendre en compteV
,L
etD
:Dans ce cas (car ce modèle utilise
^
et$
), vous feriez mieux de vérifier d'abord les lignes vides et de ne pas vous soucier de les faire correspondre. Si vous utilisez des limites de mots, vous n'avez pas de problème car il n'y a pas de mot vide. (Au moins regex n'en définit pas un; ne commencez pas à philosopher, je suis pragmatique ici!)Dans mon propre cas (dans le monde réel), j'avais besoin de faire correspondre les chiffres aux fins des mots et je n'ai trouvé aucun autre moyen de contourner cela. Je avais besoin de frotter au large des numéros de note de bas de mon document de texte brut, où le texte tel que « la mer Rouge cl et la Grande Barrière de Corail cli » avait été converti en
the Red Seacl and the Great Barrier Reefcli
. Mais j'ai toujours eu des problèmes avec des mots valides commeTahiti
etfantastic
sont frottés dansTahit
etfantasti
.la source
M
ouC
ouL
, alors, avez - vous cette sorte de regex simplifiée?(X{1,3}(IX|IV|V?I{0,3})|X{0,3}(IX|I?V|V?I{1,3}))
Heureusement, la plage de nombres est limitée à 1..3999 ou à peu près. Par conséquent, vous pouvez construire le morceau-repas regex.
Chacune de ces parties traitera des caprices de la notation romaine. Par exemple, en utilisant la notation Perl:
Répétez et assemblez.
Ajouté : Le
<opt-hundreds-part>
peut être compressé davantage:Puisque la clause 'D? C {0,3}' ne peut correspondre à rien, le point d'interrogation n'est pas nécessaire. Et, très probablement, les parenthèses devraient être du type non capturant - en Perl:
Bien sûr, tout doit également être insensible à la casse.
Vous pouvez également l'étendre pour traiter les options mentionnées par James Curran (pour autoriser XM ou IM pour 990 ou 999, et CCCC pour 400, etc.).
la source
thousands hundreds tens units
, il est facile de créer un FSM qui calcule et valide des chiffres romains donnésPour les personnes qui veulent vraiment comprendre la logique, veuillez consulter une explication étape par étape sur 3 pages sur diveintopython .
La seule différence par rapport à la solution originale (qui avait
M{0,4}
) est que j'ai trouvé que «MMMM» n'est pas un chiffre romain valide (aussi les anciens Romains n'ont probablement pas pensé à ce nombre énorme et seront en désaccord avec moi). Si vous faites partie de vieux Romains en désaccord, veuillez me pardonner et utiliser la version {0,4}.la source
Je réponds à cette question Expression régulière en Python pour les chiffres romains ici
car elle a été marquée comme un double exact de cette question.
Il peut être similaire en nom, mais il s'agit d'une question / problème spécifique aux expressions régulières,
comme le montre cette réponse à cette question.
Les éléments recherchés peuvent être combinés en une seule alternance puis
enfermés dans un groupe de capture qui sera mis dans une liste avec la fonction findall ()
.
C'est fait comme ceci:
Les modifications de regex pour factoriser et capturer uniquement les chiffres sont les suivantes:
la source
Comme Jeremy et Pax l'ont souligné plus haut ... '^ M {0,4} (CM | CD | D? C {0,3}) (XC | XL | L? X {0,3}) (IX | IV | V? I {0,3}) $ 'devrait être la solution que vous recherchez ...
L'URL spécifique qui aurait dû être jointe (IMHO) est http://thehazeltree.org/diveintopython/7.html
L'exemple 7.8 est la forme courte utilisant {n, m}
la source
Dans mon cas, j'essayais de trouver et de remplacer toutes les occurrences de nombres romains par un mot à l'intérieur du texte, donc je ne pouvais pas utiliser le début et la fin des lignes. La solution @paxdiablo a donc trouvé de nombreuses correspondances de longueur nulle. J'ai fini avec l'expression suivante:
Mon code Python final était comme ceci:
Production:
la source
Steven Levithan utilise cette regex dans son article qui valide les chiffres romains avant de "déromaniser" la valeur:
la source
J'ai vu plusieurs réponses qui ne couvrent pas les chaînes vides ou utilisent des lookaheads pour résoudre ce problème. Et je veux ajouter une nouvelle réponse qui couvre les chaînes vides et n'utilise pas lookahead. L'expression régulière est la suivante:
^(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}))$
J'autorise l'infini
M
,M+
mais bien sûr, quelqu'un pourrait changerM{1,4}
pour n'autoriser que 1 ou 4 si vous le souhaitez.Vous trouverez ci-dessous une visualisation qui aide à comprendre ce qu'il fait, précédée de deux démos en ligne:
Démo Debuggex
Démo Regex 101
la source
Cela fonctionne dans les moteurs de regex Java et PCRE et devrait maintenant fonctionner dans le dernier JavaScript, mais peut ne pas fonctionner dans tous les contextes.
(?<![A-Z])(M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3}))(?![A-Z])
La première partie est l'atroce regard négatif en arrière. Mais, pour des raisons logiques, c'est le plus facile à comprendre. Fondamentalement, le premier
(?<!)
dit ne pas correspondre au milieu([MATCH])
s'il y a des lettres avant le milieu([MATCH])
et le dernier(?!)
dit ne pas correspondre au milieu([MATCH])
s'il y a des lettres après.Le milieu
([MATCH])
est juste l'expression régulière la plus couramment utilisée pour faire correspondre la séquence de chiffres romains. Mais maintenant, vous ne voulez pas faire correspondre cela s'il y a des lettres autour.Voir par vous-même. https://regexr.com/4vce5
la source
Le problème de la solution de Jeremy et Pax est qu'elle ne correspond pas à "rien".
L'expression régulière suivante attend au moins un chiffre romain:
la source
|
peut correspondre à une chaîne vide et à tous les chiffres romains valides, donc le côté droit est complètement redondant. et oui, il correspond toujours à une chaîne vide.J'écrirais des fonctions à mon travail pour moi. Voici deux fonctions de chiffres romains dans PowerShell.
la source