[解決済み] 正規表現で有効なローマ数字のみにマッチさせるには?
質問内容
について考える その他の問題 ローマ数字にマッチする正規表現を作ることもできない(ましてや、ローマ数字を生成する文脈自由文法を作ることもできない)と判断しました。
問題は、有効なローマ数字のみをマッチングさせることです。 例えば、990は"XM"ではなく、"CMXC"です。
この正規表現を作るときに困ったのは、ある文字を許可するかしないかを決めるために、過去を振り返る必要があることです。 たとえば、千と百を考えてみましょう。
私はM{0,2}C?Mを許可することができます(900、1000、1900、2000、2900、3000を許可するため)。しかし、CMにマッチする場合、私は次の文字がCまたはDであることを許可することはできません(すでに900になっているため)。
正規表現でこれを表現するにはどうしたらよいでしょうか?
単純に正規表現ができないのであれば、文脈自由文法で表現できるのでしょうか?
どのように解決するのですか?
以下の正規表現を使用することができます。
^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
分解してみる
M{0,4}
は thousands セクションを指定し、基本的にそのセクションを
0
と
4000
. 比較的単純なものです。
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}
もちろん、以下のような使い方も可能です。
M*
を許可する
任意の
の数(0を含む)、より大きな数を許可したい場合は、千の数。
次に
(CM|CD|D?C{0,3})
少し複雑ですが、これは数百のセクションのためのもので、あらゆる可能性をカバーしています。
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
3つ目は
(XC|XL|L?X{0,3})
は、前のセクションと同じルールに従いますが、10番目の場所についてです。
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
そして、最後に。
(IX|IV|V?I{0,3})
はユニットセクションで
0
を通して
9
また、前の2つのセクションと同様です(ローマ数字は、一見奇妙に見えますが、それが何であるかを理解すれば、いくつかの論理的なルールに従います)。
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
ただ、その正規表現は空文字列にもマッチすることに留意してください。もしこれが嫌なら(そしてあなたの正規表現エンジンが十分にモダンなら)、正のlook-behindとlook-aheadを使用することができます。
(?<=^)M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})(?=$)
(もう一つの方法は、長さが0でないことを事前にチェックすることです)。
関連
-
[解決済み] 最初のマッチで停止する正規表現
-
[解決済み] 正規表現で変数を使うには?
-
[解決済み] 正規表現[^ΘdΘs]と[ΘdΘs]の違いは何ですか?
-
[解決済み] 正規表現で「逆マッチ」を行うには?
-
[解決済み] 正規表現におけるバックスラッシュの後の数値の意味は?
-
[解決済み] 単語を含まない行にマッチする正規表現
-
[解決済み] JavaScriptの正規表現でマッチしたグループにアクセスするにはどうすればよいですか?
-
[解決済み] 有効な正規表現を検出するための正規表現はありますか?
-
[解決済み] 正規表現で「この文字列までなら何でもあり」にマッチさせるには?
-
[解決済み】正規表現で「任意の文字」にマッチさせる方法とは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン