2009年 05月 13日

JavaScript の正規表現のメタ文字をエスケープ

String.prototype.replace は正規表現じゃないと ignore case しつつ global マッチとかできないけど、JavaScript には RegExp.escape 的なものがないのでメタ文字が問題になる。

var escaped = 'f[oo'.replace(/[\s\S]/g, function (_) {
    return '\\u' + (0x10000 + _.charCodeAt(0)).toString(16).slice(1)
});

'F[oobarf[oof[oo'.replace(new RegExp(escaped, 'gi'), 'xxx');

たぶんこれでいける?っぽい。正確にはメタ文字のエスケープではなくて、全部エスケープしてメタ文字を無効化しているだけですね。

ignore case しなくてよくて、search が空文字列に絶対ならないなら

'f[oobarf[oo'.split('f[oo').join('xxx');

とかもいいのかな。どんなケースでもうまくいくかまでけんしょうしていないです。(頭まわってない)

前提が抜けてて大変申し分けないのですが、

  • JS は日常的に使用される処理系がいくつもある
  • 仕様が決まっているとはいえ特定文字だけエスケープすると漏れがでる可能性がある
    • 少なくとも全ブラウザであらゆるケースをテストする必要がでてくる
  • そもそも全部列挙するのがめんどくさい

ので、最も安全で楽な形を考えた、という感じです。