Anda dapat menggunakan regex berikut untuk ini:
^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
Memecahnya, M{0,4}
menentukan bagian ribuan dan pada dasarnya menahannya antara 0
dan 4000
. Ini relatif sederhana:
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}
Anda bisa, tentu saja, menggunakan sesuatu seperti M*
mengizinkan angka berapa pun (termasuk nol) ribuan, jika Anda ingin memperbolehkan angka yang lebih besar.
Berikutnya adalah (CM|CD|D?C{0,3})
, sedikit lebih kompleks, ini untuk bagian ratusan dan mencakup semua kemungkinan:
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
Ketiga, (XC|XL|L?X{0,3})
ikuti aturan yang sama seperti bagian sebelumnya tetapi untuk tempat puluhan:
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
Dan, akhirnya, (IX|IV|V?I{0,3})
adalah bagian unit, penanganan 0
melalui 9
dan juga mirip dengan dua bagian sebelumnya (angka Romawi, meskipun keanehan tampak mereka, mengikuti beberapa aturan yang logis setelah Anda mengetahui apa yang mereka):
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
Perlu diingat bahwa regex itu juga akan cocok dengan string kosong. Jika Anda tidak menginginkan ini (dan mesin regex Anda cukup modern), Anda dapat menggunakan pandangan ke belakang dan melihat ke depan:
(?<=^)M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})(?=$)
(Alternatif lain adalah hanya memeriksa bahwa panjangnya tidak nol sebelumnya).
MMMM
adalah cara yang benar. Representasi overbar datang jauh setelah kerajaan inti hancur berkeping-keping./^M{0,3}(?:C[MD]|D?C{0,3})(?:X[CL]|L?X{0,3})(?:I[XV]|V?I{0,3})$/i
Sebenarnya, premis Anda cacat. 990 IS "XM", serta "CMXC".
Bangsa Romawi tidak terlalu peduli tentang "aturan" daripada guru kelas tiga Anda. Selama ditambahkan, itu OK. Karenanya "IIII" sama baiknya dengan "IV" untuk 4. Dan "IIM" benar-benar keren untuk 998.
(Jika Anda mengalami kesulitan menangani itu ... Ingat ejaan bahasa Inggris tidak diformalkan sampai tahun 1700-an. Sampai saat itu, selama pembaca dapat mengetahuinya, itu cukup baik).
sumber
Untuk menyimpannya di sini:
Cocok dengan semua angka Romawi. Tidak peduli dengan string kosong (membutuhkan setidaknya satu huruf angka Romawi). Harus bekerja di PCRE, Perl, Python, dan Ruby.
Demo Ruby online: http://rubular.com/r/KLPR1zq3Hj
Konversi Online: http://www.onlineconversion.com/roman_numerals_advanced.htm
sumber
Untuk menghindari pencocokan string kosong Anda harus mengulangi pola empat kali dan mengganti masing
0
- masing dengan1
pada gilirannya, dan akun untukV
,L
danD
:Dalam hal ini (karena pola ini menggunakan
^
dan$
) Anda akan lebih baik memeriksa baris kosong terlebih dahulu dan jangan repot-repot mencocokkannya. Jika Anda menggunakan batas kata maka Anda tidak memiliki masalah karena tidak ada kata kosong. (Setidaknya regex tidak mendefinisikan satu; jangan mulai berfilsafat, saya bersikap pragmatis di sini!)Dalam kasus (dunia nyata) saya sendiri, saya membutuhkan angka yang cocok pada akhir kata dan saya tidak menemukan cara lain untuk mengatasinya. Saya butuhkan untuk menggosok off nomor catatan kaki dari dokumen teks biasa saya, di mana teks seperti "Laut Merah cl dan Great Barrier Reef cli " telah dikonversi ke
the Red Seacl and the Great Barrier Reefcli
. Tapi saya masih punya masalah dengan kata-kata yang valid sepertiTahiti
danfantastic
digosok ke dalamTahit
danfantasti
.sumber
M
atauC
atauL
, sehingga, apakah Anda memiliki ini jenis regex yang disederhanakan?(X{1,3}(IX|IV|V?I{0,3})|X{0,3}(IX|I?V|V?I{1,3}))
Untungnya, kisaran angka terbatas pada 1..3999 atau sekitar itu. Oleh karena itu, Anda dapat membangun sepotong makan regex.
Masing-masing bagian akan berurusan dengan tingkah laku notasi Romawi. Misalnya, menggunakan notasi Perl:
Ulangi dan rakit.
Ditambahkan :
<opt-hundreds-part>
Dapat dikompresi lebih lanjut:Karena klausa 'D? C {0,3}' tidak cocok dengan apa pun, tidak perlu ada tanda tanya. Dan, kemungkinan besar, tanda kurung harus menjadi tipe yang tidak menangkap - di Perl:
Tentu saja, semua harus case-sensitive juga.
Anda juga dapat memperluas ini untuk menangani opsi yang disebutkan oleh James Curran (untuk memungkinkan XM atau IM untuk 990 atau 999, dan CCCC untuk 400, dll).
sumber
thousands hundreds tens units
, mudah untuk membuat FSM yang menghitung dan memvalidasi angka RomawiBagi orang yang benar-benar ingin memahami logika, silakan lihat penjelasan langkah demi langkah pada 3 halaman tentang diveintopython .
Satu-satunya perbedaan dari solusi asli (yang dimiliki
M{0,4}
) adalah karena saya menemukan bahwa 'MMMM' bukan angka Romawi yang valid (juga orang Romawi lama kemungkinan besar belum memikirkan jumlah yang besar itu dan tidak akan setuju dengan saya). Jika Anda salah satu dari orang Romawi yang tidak setuju, tolong maafkan saya dan gunakan versi {0,4}.sumber
Saya menjawab pertanyaan ini Ekspresi Reguler dalam Python untuk Angka Romawi di sini
karena itu ditandai sebagai duplikat yang tepat dari pertanyaan ini.
Mungkin mirip dalam nama, tetapi ini adalah pertanyaan / masalah regex spesifik
seperti yang dapat dilihat oleh jawaban untuk pertanyaan itu.
Item yang dicari dapat digabungkan menjadi satu pergantian tunggal dan kemudian
terbungkus di dalam grup tangkap yang akan dimasukkan ke dalam daftar dengan fungsi findall ()
.
Ini dilakukan seperti ini:
Modifikasi regex untuk faktor dan menangkap hanya angka adalah ini:
sumber
Seperti ditunjukkan Jeremy dan Pax di atas ... '^ M {0,4} (CM | CD | D? C {0,3}) (XC | XL | L? X {0,3}) (IX | IV | V? Saya {0,3}) $ 'harus menjadi solusi yang Anda cari ...
URL spesifik yang seharusnya dilampirkan (IMHO) adalah http://thehazeltree.org/diveintopython/7.html
Contoh 7.8 adalah formulir singkat menggunakan {n, m}
sumber
Dalam kasus saya, saya mencoba mencari dan mengganti semua kemunculan angka romawi dengan satu kata di dalam teks, jadi saya tidak bisa menggunakan awal dan akhir baris. Jadi solusi @paxdiablo menemukan banyak kecocokan dengan panjang nol. Saya berakhir dengan ungkapan berikut:
Kode Python terakhir saya adalah seperti ini:
Keluaran:
sumber
Steven Levithan menggunakan regex ini dalam posnya yang memvalidasi angka romawi sebelum "menghilangkan nilai" nilainya:
sumber
Saya telah melihat beberapa jawaban yang tidak mencakup string kosong atau menggunakan lookaheads untuk menyelesaikan ini. Dan saya ingin menambahkan jawaban baru yang mencakup string kosong dan tidak menggunakan lookahead. Regex adalah yang berikut:
^(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}))$
Saya mengizinkan untuk yang tak terbatas
M
, denganM+
tetapi tentu saja seseorang dapat berubahM{1,4}
untuk mengizinkan hanya 1 atau 4 jika diinginkan.Di bawah ini adalah visualisasi yang membantu untuk memahami apa yang dilakukannya, didahului oleh dua demo online:
Demo Debuggex
Regex 101 Demo
sumber
Ini berfungsi di mesin regex Java dan PCRE dan sekarang harus berfungsi dalam JavaScript terbaru tetapi mungkin tidak berfungsi di semua konteks.
(?<![A-Z])(M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3}))(?![A-Z])
Bagian pertama adalah tampilan negatif yang mengerikan. Tapi, untuk tujuan logis, ini yang paling mudah dipahami. Pada dasarnya, yang pertama
(?<!)
mengatakan tidak cocok dengan tengah([MATCH])
jika ada huruf yang datang sebelum tengah([MATCH])
dan yang terakhir(?!)
mengatakan tidak cocok dengan tengah([MATCH])
jika ada huruf yang datang setelah itu.Bagian tengah
([MATCH])
hanyalah regex yang paling umum digunakan untuk mencocokkan urutan Angka Romawi. Tapi sekarang, Anda tidak ingin mencocokkannya jika ada surat di sekitarnya.Lihat diri mu sendiri. https://regexr.com/4vce5
sumber
Masalah dari solusi dari Jeremy dan Pax adalah, itu tidak cocok dengan "tidak ada".
Regex berikut ini mengharapkan setidaknya satu angka romawi:
sumber
|
dapat mencocokkan string kosong dan semua angka romawi yang valid, sehingga sisi kanan sepenuhnya mubazir. dan ya, itu masih cocok dengan string kosong.Saya akan menulis fungsi untuk pekerjaan saya untuk saya. Berikut adalah dua fungsi angka romawi di PowerShell.
sumber