Bagaimana saya bisa menggunakan ekspresi reguler Unicode-aware dalam JavaScript?
Misalnya, harus ada sesuatu yang serupa dengan \w
yang dapat cocok dengan titik kode apa pun dalam kategori Letters atau Marks (bukan hanya yang ASCII), dan mudah-mudahan memiliki filter seperti [[P *]] untuk tanda baca, dll.
javascript
regex
unicode
character-properties
Peter Mortensen
sumber
sumber
Jawaban:
Situasi untuk ES 6
Spesifikasi bahasa ECMAScript mendatang, edisi 6, termasuk ekspresi reguler yang sadar Unicode. Dukungan harus diaktifkan dengan
u
pengubah pada regex. Lihat ekspresi reguler Unicode-aware di ES6 .Sampai ES 6 selesai dan banyak diadopsi di antara vendor browser Anda masih sendiri. Pembaruan: Sekarang ada transpiler bernama regexpu yang menerjemahkan ekspresi reguler ES6 Unicode menjadi ES5 yang setara. Ini dapat digunakan sebagai bagian dari proses pembuatan Anda. Cobalah online.
Situasi untuk ES 5 dan di bawah
Meskipun JavaScript beroperasi pada string Unicode, ia tidak mengimplementasikan kelas karakter yang sadar Unicode dan tidak memiliki konsep kelas karakter POSIX atau blok / sub-rentang Unicode.
Masalah dengan Unicode dalam ekspresi reguler JavaScript
Periksa harapan Anda di sini: Javascript RegExp Unicode Character Class tester ( Edit: halaman asli turun, Arsip Internet masih memiliki salinan .)
Flagrant Badassery memiliki artikel tentang JavaScript, Regex, dan Unicode yang menjelaskan masalah ini.
Baca juga Regex dan Unicode di sini di SO. Mungkin Anda harus membangun "kelas karakter tanda baca" Anda sendiri.
Lihat Ekspresi Reguler: Pencocokan Unicode Block Range builder, yang memungkinkan Anda membangun ekspresi reguler JavaScript yang cocok dengan karakter yang termasuk sejumlah blok Unicode yang ditentukan.
Saya baru saja melakukannya untuk sub-rentang "Tanda Baca Umum" dan "Tanda Baca Tambahan", dan hasilnya sederhana dan langsung seperti yang saya harapkan:
Ada juga XRegExp , sebuah proyek yang membawa dukungan Unicode ke JavaScript dengan menawarkan mesin regex alternatif dengan kemampuan yang diperluas.
Dan tentu saja, bacaan wajib: mathiasbynens.be - JavaScript memiliki masalah Unicode :
sumber
u
bendera serta beberapa lainnya ES6 fitur untuk bekerja dengan Unicode.u
ekspresi reguler itu."a品cd!e f".replace(/[^\w]/ug, "")
dan tetapi regex yang dihasilkan (dijalankan di Chrome 59) masih menghilangkan品
karakter dan hanya kembali"acdef"
Secara pribadi, saya lebih suka tidak menginstal perpustakaan lain hanya untuk mendapatkan fungsi ini. Jawaban saya tidak memerlukan perpustakaan eksternal, dan mungkin juga berfungsi dengan sedikit modifikasi untuk rasa regex selain JavaScript.
Situs web Unicode menyediakan cara untuk menerjemahkan kategori Unicode ke dalam satu set poin kode. Karena ini situs web Unicode , informasi darinya harus akurat.
Perhatikan bahwa Anda harus mengecualikan karakter kelas atas, karena JavaScript hanya dapat menangani karakter kurang dari
FFFF
(hex). Saya sarankan untuk mencentang kotak Singkatan Singkatan, dan Escape, yang menyeimbangkan antara menghindari karakter yang tidak patut dan meminimalkan ukuran regex.Berikut adalah beberapa perluasan umum dari sifat Unicode yang berbeda:
\p{L}
(Surat):\p{Nd}
(Angka angka desimal):\p{P}
(Tanda Baca):Halaman ini juga mengenali sejumlah kelas karakter yang tidak jelas, seperti
\p{Hira}
, yang hanya karakter Hiragana (Jepang):Terakhir, dimungkinkan untuk memasang kelas char dengan lebih dari satu properti Unicode untuk mendapatkan regex yang lebih pendek daripada yang Anda dapatkan hanya dengan menggabungkannya (selama pengaturan tertentu dicentang).
sumber
\p
-Syntax tampaknya tidak berfungsi di JS,/\p{L}/.test('a')
adalahfalse
Setelah juga tidak menemukan solusi yang baik, saya menulis skrip kecil beberapa waktu yang lalu, dengan mengunduh data dari spesifikasi unicode (v.5.0.0) dan menghasilkan interval untuk setiap kategori dan subkategori unicode di BMP (akhir-akhir ini digantikan oleh yang kecil Program Java yang menggunakan dukungan Unicode asalnya sendiri).
Pada dasarnya itu dikonversi
\p{...}
ke berbagai nilai, seperti output dari alat yang disebutkan oleh Tomalak, tetapi intervalnya bisa berakhir cukup besar (karena tidak berurusan dengan blok, tetapi dengan karakter yang tersebar di banyak tempat yang berbeda).Misalnya, sebuah Regex ditulis seperti ini:
Akan dikonversi menjadi seperti ini:
Belum banyak menggunakannya dalam praktik, tetapi tampaknya berfungsi dengan baik dari tes saya, jadi saya memposting di sini kalau-kalau ada yang merasa berguna. Terlepas dari panjang regex yang dihasilkan (contoh di atas memiliki 3591 karakter saat diperluas), kinerjanya tampaknya dapat diterima (lihat tes di jsFiddle; terima kasih kepada @modiX dan @Lwangaman untuk perbaikannya).
Berikut sumber (mentah, 27.5KB; minified , 24.9KB, tidak jauh lebih baik ...). Ini mungkin dibuat lebih kecil oleh pembatalan penggantian karakter karakter unicode, tapi Otoh akan menjalankan risiko masalah encoding, jadi aku meninggalkan seperti itu. Semoga dengan ES6 hal semacam ini tidak diperlukan lagi.
Pembaruan : ini terlihat seperti strategi yang sama yang diadopsi dalam plug-in Unicode XRegExp yang disebutkan oleh Tim Down, kecuali bahwa dalam hal ini regex JavaScript biasa sedang digunakan.
sumber
/^\p{L}+$/
harus cocok東海林
tetapi tidak. Setiap kali Anda memperbarui koleksi, informasikan kepada saya. Terima kasih banyak.\p{Lo}
, Anda kehilangan kedua tabel Kanji di dalamnya.Seperti disebutkan dalam jawaban lain, regex JavaScript tidak memiliki dukungan untuk kelas karakter Unicode. Namun, ada perpustakaan yang menyediakan ini: Steven Levithan XRegExp yang sangat baik dan plug-in Unicode-nya .
sumber
[^\u0000-\u007F]+
untuk setiap karakter yang tidak termasuk karakter ASCII.Sebagai contoh:
Berikut ini beberapa referensi sempurna:
Generator RegExp dengan kisaran Unicode
Ekspresi Reguler Unicode
Unicode 10.0 Diagram Kode Karakter
Cocokkan Rentang Blok Unicode
sumber
September 2018 (diperbarui Februari 2019)
Tampaknya regexp
/\p{L}/u
untuk huruf yang cocok (sebagai kategori unicode )Berikut ini contoh kerjanya
Saya melaporkan bug ini di sini .
Memperbarui
Setelah lebih dari 2 tahun, menurut: 1500035 > 1361876 > 1634135 akhirnya bug ini diperbaiki dan akan tersedia di Firefox v.78 +
sumber
Ini akan melakukannya:
Itu secara eksplisit memilih berbagai karakter unicode. Ini akan berfungsi untuk karakter latin, tetapi karakter aneh lainnya mungkin berada di luar kisaran ini.
sumber
\u0100
dan\u0280
: banyak dari mereka dapat dianggap sebagai karakter latin tetapi yang lain tidak: var s = ''; for (var i = 0xff; i <= 0x280; i ++) {s + = String.fromCharCode (i)} "ÿĀāĂ㥹ĆćĈĉĊċČčĎďĐđĒēĔĕĖėĘęĚěĜĝĞğĠġĢģĤĥĦħĨĩĪīĬĭĮįİıIJijĴĵĶķĸĹĺĻļĽľĿŀŁłŃńŅņŇňʼnŊŋŌōŎŏ ... ǐǑǒǓǔǕǖǗǘǙǚǛǜǝǞǟǠǡǢǣǤǥǦǧǨǩǪǫǬǭǮǯǰDZDzdzǴǵǶǷǸǹǺǻǼǽǾǿȀȁȂȃȄȅȆȇȈȉȊȋȌȍȎȏȐȑȒȓȔȕȖȗȘșȚțȜȝȞȟȠȡȢȣȤȥȦȧȨȩȪȫȬȭȮȯȰȱȲȳȴȵȶȷȸȹȺȻȼȽȾȿɀɁɂɃɄɅɆɇɈɉɊɋɌɍɎɏɐɑɒɓɔɕɖɗɘəɚɛɜɝɞɟɠɡɢɣɤɥɦɧɨɩɪɫɬɭɮɯɰɱɲɳɴɵɶɷɸɹɺɻɼɽɾɿʀ"Dalam JavaScript, \ w dan \ d adalah ASCII, sementara itu adalah Unicode. Jangan tanya kenapa. JavaScript mendukung \ p dengan kategori Unicode, yang dapat Anda gunakan untuk meniru Unicode-aware \ w and \ d.
Untuk \ d gunakan \ p {N} (angka)
Untuk \ w gunakan [\ p {L} \ p {N} \ p {Pc} \ p {M}] (huruf, angka, garis bawah, tanda)
Pembaruan: Sayangnya, saya salah tentang ini. JavaScript juga tidak secara resmi mendukung \ p, meskipun beberapa implementasi mungkin masih mendukung ini. Satu-satunya dukungan Unicode di regex JavaScript adalah mencocokkan poin kode tertentu dengan \ uFFFF. Anda bisa menggunakannya dalam rentang di kelas karakter.
sumber
/\p{L}+/u
Jika Anda menggunakan Babel maka dukungan Unicode sudah tersedia.
Saya juga merilis sebuah plugin yang mengubah kode sumber Anda sehingga Anda dapat menulis ekspresi reguler seperti
/^\p{L}+$/
. Ini kemudian akan diubah menjadi sesuatu yang dimengerti browser.Ini adalah halaman proyek plugin:
babel-plugin-utf-8-regex
sumber
Saya menjawab pertanyaan ini.
Apa yang akan setara dengan \ p {Lu} atau \ p {Ll} di regExp untuk js?
karena itu ditandai sebagai duplikat yang tepat dari pertanyaan lama saat ini.
Meminta Basis Data UCD dari Unicode 12, \ p {Lu} menghasilkan 1.788 poin kode.
Konversi ke UTF-16 menghasilkan kesetaraan konstruk kelas.
Ini hanya string karakter 4k dan mudah dilakukan di mesin regex apa pun.
Meminta basis data UCD dari Unicode 12, \ p {Ll} menghasilkan 2.151 poin kode.
Konversi ke UTF-16 menghasilkan kesetaraan konstruk kelas.
Perhatikan bahwa implementasi regex dari \ p {Lu} atau \ p {Pl} sebenarnya memanggil
fungsi yang tidak standar untuk menguji nilainya.
Kelas karakter yang ditampilkan di sini dilakukan secara berbeda dan linear, standar,
dan cukup lambat, ketika macet menjadi sebagian besar kelas tunggal.
Beberapa wawasan tentang bagaimana mesin Regex (secara umum) mengimplementasikan Kelas Properti Unicode:
Periksa karakteristik kinerja ini antara properti
dan blok kelas (seperti di atas)
Wow, apa bedanya !!
Mari kita lihat bagaimana Properties diimplementasikan
Array of Pointers [10FFFF] di mana setiap indeks adalah Code Point
Setiap pointer dalam Array adalah struktur klasifikasi.
Struktur Klasifikasi berisi elemet bidang tetap.
Beberapa NULL dan tidak berkaitan.
Beberapa mengandung klasifikasi kategori.
Contoh: Kategori Umum
Ini adalah elemen yang dipetakan menggunakan 17 dari 64 bit.
Apa pun yang didukung oleh Code Point ini, bit ditetapkan sebagai topeng.
-Close_Punctuation
-Connector_Punctuation
-Kontrol
-Currency_Symbol
-Dash_Punctuation
-Decimal_Number
-Enclosing_Mark
-Final_Punctuation
-format
-Initial_Punctuation
-Letter_Number
-Line_Separator
-Lowercase_Letter
-Math_Symbol
-Modifier_Letter
-Modifier_Symbol
-Nonspacing_Mark
-Open_Punctuation
-Other_Letter
-Other_Number
-Other_Punctuation
-Other_Symbol
-Paragraph_Separator
-Private_Use
-Space_Separator
-Spacing_Mark
-Surrogate
-Titlecase_Letter
-Unassigned
-Uppercase_Letter
Ketika sebuah regex diuraikan dengan sesuatu seperti ini \ p {Lu} itu
diterjemahkan langsung ke
Contoh lain, ketika regex diuraikan dengan properti tanda baca \ p {P} itu
diterjemahkan ke dalam
Pemeriksaan elemen tersebut untuk bit item ini, yang digabungkan ke dalam mask:
-Close_Punctuation
-Connector_Punctuation
-Dash_Punctuation
-Final_Punctuation
-Initial_Punctuation
-Open_Punctuation
-Other_Punctuation
Offset dan bit atau bit (mask) disimpan sebagai langkah regex untuk properti itu.
Tabel pencarian dibuat sekali untuk semua Poin Kode Unicode menggunakan array ini.
Ketika sebuah karakter dicentang, sesederhana menggunakan CP sebagai indeks ke dalam array ini dan memeriksa elemen spesifik Struktur Klasifikasi untuk bit itu (mask).
Struktur ini dapat diperluas dan tidak langsung untuk memberikan tampilan yang jauh lebih kompleks. Ini hanyalah contoh sederhana.
Bandingkan pencarian langsung itu dengan pencarian kelas karakter:
Semua kelas adalah daftar linier item yang dicari dari kiri ke kanan.
Dalam perbandingan ini, mengingat string target kami hanya berisi Huruf Unicode Huruf lengkap lengkap saja, hukum rata-rata akan memperkirakan bahwa setengah dari item di kelas harus diperiksa untuk menemukan kecocokan.
Ini adalah kerugian besar dalam kinerja.
Namun, jika tabel pencarian tidak ada atau tidak mutakhir dengan rilis Unicode terbaru (12 per tanggal ini)
maka ini akan menjadi satu-satunya cara.
Bahkan, sebagian besar merupakan satu-satunya cara untuk mendapatkan
karakter Emoji yang lengkap karena tidak ada properti khusus (atau alasan) untuk penugasan mereka.
sumber
Anda juga bisa menggunakan:
sumber