正規表現で使用する文字をエスケープする

はじめに

正規表現でユーザ入力を処理する場合、エスケープ処理が必要になってきます。正規表現を使用した文字列のエスケープについて考えます。

MDNのサンプルコード

JavaScriptのサンプルコードと言えば、おなじみのMDNです。調べてみると、正規表現のページの中にこっそりとサンプルコードが置かれていました。次のコードがそれになります。

// see https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
function escapeRegExp(string) {
  return string.replace(/[.*+?^=!:${}()|[\]\/\\]/g, '\\$&'); // $&はマッチした部分文字列全体を意味します
}

※上記のコードでは、「-」がエスケープされません(漏れているように感じます)
 new RegExp("["+escapeRegExp("a+b-c")+"]", "g").test("-") // false
 翻訳前の原文も同様の処理でした

自作する

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領域内にしかない
  • 特殊な文字は、機能拡張によって増加することがある