はじめに
正規表現でユーザ入力を処理する場合、エスケープ処理が必要になってきます。正規表現を使用した文字列のエスケープについて考えていきます。
MDNのサンプルコード
JavaScriptのサンプルコードならば、皆さんおなじみのMDNです。調べてみると、正規表現のページの中にこっそりとサンプルコードが置かれていました。次のコードがそれになります。
// see https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions (最終閲覧日 2020年02月14日)
function escapeRegExp(string) {
return string.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&'); // $&はマッチした部分文字列全体を意味します
}
※上記のコードでは、「-」がエスケープされない(漏れているように感じます)
new RegExp("["+escapeRegExp("a+b-c")+"]", "g").test("-") // false
翻訳前の原文も同様だったため、下記のように編集申請してみました。
// see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions (最終閲覧日 2020年02月14日)
function escapeRegExp(string) {
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
自作する
MDNのコードも怪しめなので、別の考え方で自作してみます。
考え方は、「数字、大文字アルファベット、小文字アルファベット以外のASCII領域の文字をエスケープする」です。具体的には、次の範囲をエスケープします。
- ASCII領域: \x00-\x7F
- [0-9]: \x30-\x39
- エスケープシーケンスの例:
\0
=NULL文字
- エスケープシーケンスの例:
- [A-Z]: \x41-\x5A
- エスケープシーケンスの例:
\D
=数字以外
- エスケープシーケンスの例:
- [a-z]: \x61-\x7A
- エスケープシーケンスの例:
\d
=数字
- エスケープシーケンスの例:
- ASCII領域内で上記以外: \x00-\x2F, \x3A-\x40, \x5B-\x60, \x7B-\x7F
function escapeRegExp(string) {
return string.replace(/([\x00-\x2F\x3A-\x40\x5B-\x60\x7B-\x7F])/g, '\\$&')
}
※前提:エスケープシーケンスは、数字と大小アルファベットのみ
※前提:特殊な文字は、ASCII領域内にしかない
※前提:特殊な文字は、機能拡張によって増加することがある