Saya hanya ingin membuat ekspresi reguler dari string yang mungkin.
var usersString = "Hello?!*`~World()[]";
var expression = new RegExp(RegExp.escape(usersString))
var matches = "Hello".match(expression);
Apakah ada metode bawaan untuk itu? Jika tidak, apa yang digunakan orang? Ruby punya RegExp.escape
. Saya tidak merasa perlu menulis sendiri, pasti ada sesuatu yang standar di luar sana. Terima kasih!
javascript
regex
Lance Pollard
sumber
sumber
RegExp.escape
sedang bekerja dan siapa pun yang berpikir mereka memiliki input yang berharga sangat dipersilakan untuk berkontribusi. core-js dan polyfill lain menawarkannya.Jawaban:
Fungsi yang ditautkan di atas tidak cukup. Gagal melarikan diri
^
atau$
(mulai dan akhir string), atau-
, yang dalam grup karakter digunakan untuk rentang.Gunakan fungsi ini:
Meskipun mungkin tampak tidak perlu pada pandangan pertama, melarikan diri
-
(dan juga^
) membuat fungsi yang cocok untuk melarikan diri karakter yang akan dimasukkan ke dalam kelas karakter serta tubuh regex.Lolos
/
membuat fungsi yang cocok untuk melarikan diri karakter yang akan digunakan dalam JS regex literal untuk eval nanti.Karena tidak ada kerugian untuk melarikan diri dari keduanya, masuk akal untuk melarikan diri untuk membahas kasus penggunaan yang lebih luas.
Dan ya, gagal mengecewakan karena ini bukan bagian dari JavaScript standar.
sumber
/
sama sekaliquotemeta
(\Q
), Pythonre.escape
, PHPpreg_quote
, RubyRegexp.quote
...var e = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;
dan kemudian fungsi Anda adalahreturn s.replace(e, '\\$&');
Dengan cara ini Anda hanya instantiate RegExp sekali.RegExp.escape
implementasinya yang berbeda dengan Anda? Bukankah lebih baik fungsi ini tidak melekat pada apa pun?Bagi siapa pun yang menggunakan lodash, karena v3.0.0 fungsi _.escapeRegExp sudah ada di dalamnya :
Dan, jika Anda tidak ingin memerlukan perpustakaan lodash lengkap, Anda mungkin hanya memerlukan fungsi itu !
sumber
escapeRegExp
fungsi.Sebagian besar ekspresi di sini menyelesaikan kasus penggunaan tunggal spesifik.
Tidak apa-apa, tapi saya lebih suka pendekatan "selalu berhasil".
Ini akan "sepenuhnya keluar" dari string literal untuk penggunaan berikut dalam ekspresi reguler:
new RegExp(regExpEscape(str))
new RegExp('[' + regExpEscape(str) + ']')
new RegExp('x{1,' + regExpEscape(str) + '}')
Karakter Khusus yang Dicakup:
-
: Membuat rentang karakter dalam kelas karakter.[
/]
: Memulai / mengakhiri kelas karakter.{
/}
: Memulai / mengakhiri specifier angka.(
/)
: Memulai / mengakhiri grup.*
/+
/?
: Menentukan jenis pengulangan..
: Cocok dengan karakter apa pun.\
: Melepaskan karakter, dan memulai entitas.^
: Menentukan mulai dari zona pencocokan, dan meniadakan pencocokan di kelas karakter.$
: Menentukan akhir zona pencocokan.|
: Menentukan pergantian.#
: Menentukan komentar dalam mode jarak bebas.\s
: Diabaikan dalam mode jarak bebas.,
: Memisahkan nilai dalam penentu angka./
: Memulai atau mengakhiri ekspresi.:
: Menyelesaikan tipe grup khusus, dan bagian dari kelas karakter Perl-style.!
: Meniadakan grup dengan lebar nol.<
/=
: Bagian dari spesifikasi grup nol-lebar.Catatan:
/
tidak sepenuhnya diperlukan dalam rasa ekspresi reguler. Namun, itu melindungi jika seseorang (gemetaran) tidakeval("/" + pattern + "/");
.,
memastikan bahwa jika string dimaksudkan sebagai bilangan bulat dalam penentu angka, itu akan menyebabkan kesalahan kompilasi RegExp alih-alih diam-diam mengkompilasi yang salah.#
, dan\s
tidak perlu melarikan diri dalam JavaScript, tetapi lakukan dalam banyak rasa lainnya. Mereka melarikan diri di sini kalau-kalau ekspresi reguler nanti akan diteruskan ke program lain.Jika Anda juga perlu untuk membuktikan di masa depan ekspresi reguler terhadap potensi penambahan kemampuan mesin regex JavaScript, saya sarankan menggunakan yang lebih paranoid:
Fungsi ini lolos dari setiap karakter kecuali yang dijamin secara eksplisit tidak akan digunakan untuk sintaks dalam rasa ekspresi reguler di masa mendatang.
Untuk yang benar-benar sanitasi, pertimbangkan kasus tepi ini:
Ini harus dikompilasi dengan baik dalam JavaScript, tetapi tidak dalam beberapa rasa lainnya. Jika ingin beralih ke rasa lain, null case
s === ''
harus diperiksa secara independen, seperti:sumber
/
perlu melarikan diri di[...]
kelas karakter.Panduan Jaringan Pengembang Mozilla untuk Ekspresi Reguler menyediakan fungsi pelolosan ini:
sumber
=
tidak lagi disertakan.Dalam widget autocomplete jQueryUI (versi 1.9.1) mereka menggunakan regex yang sedikit berbeda (Line 6753), inilah ekspresi reguler yang dikombinasikan dengan pendekatan @bobince.
sumber
,
(yang bukan merupakan metacharacter), dan#
dan spasi putih yang hanya penting dalam mode spasi bebas (yang tidak didukung oleh JavaScript). Namun, mereka melakukannya dengan benar agar tidak luput dari tebasan ke depan.$.ui.autocomplete.escapeRegex(myString)
.Tidak ada yang mencegah Anda dari melarikan diri setiap karakter non-alfanumerik:
Anda kehilangan tingkat keterbacaan tertentu ketika melakukannya
re.toString()
tetapi Anda memenangkan banyak kesederhanaan (dan keamanan).Menurut ECMA-262, di satu sisi, ekspresi reguler "sintaks karakter" selalu non-alfanumerik, sehingga hasilnya adalah aman, dan escape sequence khusus (
\d
,\w
,\n
) selalu alfanumerik sehingga tidak ada lolos kontrol palsu akan diproduksi .sumber
.replace(/[^\w]/g, '\\$&')
akan bekerja dengan cara yang sama.new RegExp('🍎'.replace(/(?=\W)/g, '\\'), 'u')
melempar pengecualian karena\W
cocok dengan masing-masing unit kode pasangan pengganti secara terpisah, sehingga menghasilkan kode melarikan diri yang tidak valid..replace(/\W/g, "\\$&");
Ada proposal ES7 untuk RegExp.escape di https://github.com/benjamingr/RexExp.escape/ , dengan polyfill tersedia di https://github.com/ljharb/regexp.escape .
sumber
Ini adalah versi yang lebih pendek.
Ini termasuk karakter non-meta dari
%
,&
,'
, dan,
, namun spesifikasi JavaScript RegExp memungkinkan ini.sumber
.
tidak terjawab. Dan()
. Atau tidak?[-^
aneh. Saya tidak ingat apa yang ada di sana.XRegExp memiliki fungsi pelarian:
XRegExp.escape('Escaped? <.>'); // -> 'Escaped\?\ <\.>'
Lebih lanjut tentang: http://xregexp.com/api/#escape
sumber
Daripada hanya melarikan diri karakter yang akan menyebabkan masalah dalam ekspresi reguler Anda (misalnya: daftar hitam), mengapa tidak mempertimbangkan menggunakan daftar putih saja. Dengan cara ini setiap karakter dianggap ternoda kecuali cocok.
Untuk contoh ini, asumsikan ungkapan berikut:
Ini daftar putih huruf, angka dan spasi:
Pengembalian:
Ini mungkin lolos dari karakter yang tidak perlu melarikan diri, tetapi ini tidak menghalangi ekspresi Anda (mungkin beberapa hukuman waktu kecil - tapi itu layak untuk keselamatan).
sumber
sumber
Fungsi-fungsi dalam jawaban lain terlalu banyak untuk melarikan diri dari seluruh ekspresi reguler (mereka mungkin berguna untuk keluar dari bagian ekspresi reguler yang nantinya akan digabungkan ke dalam regexps yang lebih besar).
Jika Anda melarikan diri seluruh regexp dan selesai dengan hal itu, mengutip metakarakter yang baik standalone (
.
,?
,+
,*
,^
,$
,|
,\
) atau memulai sesuatu ((
,[
,{
) adalah semua yang Anda perlu:Dan ya, mengecewakan bahwa JavaScript tidak memiliki fungsi seperti bawaan ini.
sumber
(text)next
dan masukkan:(?:
+ input +)
. Metode Anda akan memberikan string(?:\(text)next)
yang dihasilkan yang gagal dikompilasi. Perhatikan bahwa ini adalah penyisipan yang cukup masuk akal, bukan yang gila sepertire\
+ input +re
(dalam hal ini, programmer dapat disalahkan karena melakukan sesuatu yang bodoh)\
harus diloloskan, karena regex Anda akan\w
tetap utuh. Selain itu, JavaScript tampaknya tidak mengizinkan penelusuran)
, setidaknya itulah yang menyebabkan kesalahan Firefox.)
Pendekatan lain (jauh lebih aman) adalah keluar dari semua karakter (dan bukan hanya beberapa karakter khusus yang saat ini kita kenal) menggunakan format escape unicode
\u{code}
:Harap dicatat bahwa Anda harus melewati
u
bendera agar metode ini berfungsi:sumber
Hanya ada dan akan pernah ada 12 meta karakter yang perlu dilepaskan
untuk dianggap literal.
Tidak masalah apa yang dilakukan dengan string yang lolos, dimasukkan ke dalam
pembungkus regex yang seimbang , ditambahkan, tidak masalah.
Lakukan penggantian string menggunakan ini
sumber
]
?