LoginSignup
26
18

More than 5 years have passed since last update.

new RegExp と String.raw の相性が割と良かった

Posted at

文字列を正規表現オブジェクトにするときの問題

例えば

re = /hoge\s*fuga/i

みたいな正規表現のfugaの部分に変数を使いたいときはRegExpを使えばいいのですが、

str = "fuga"
re = new RegExp("hoge\s" + str, "i");

とすると意味が変わってしまいます。これは"hoge\s"が文字列としての値を返す際にバックスラッシュの処理がなされ、実際には「hoges」という文字列になっているからです。そのため、

str = "fuga"
re = new RegExp("hoge\\s" + str, "i")

のようにしなければなりません。

正規表現:RegExp('Hello\sworld!')はマッチしない

タグ付けテンプレートリテラルが便利

ES2015(ES6)で、テンプレートリテラルが加わると同時に文字列をエスケープせずそのまま扱うための仕組みも加わりました。

JavaScript の テンプレートリテラル を極める!

これを使うとなんと、

str = "fuga"
re = new RegExp(String.raw`hoge\s${str}`, "i")

のように書けちゃいます。バックスラッシュが一回でいい上、変数が埋め込めて便利です。

もっと複雑な例をあげてみます。\(^o^)/にマッチする正規表現の場合、

re = /\\\(\^o\^\)\//

です(なんかキモい)。この口の部分を変数で指定したいとき、従来だと

mouth = "o"
re = new RegExp("\\\\\\(\\^" + mouth + "\\^\\)/")

となりもはや何をやっているかわかりませんが、String.rawを使えば

mouth = "o"
re = new RegExp(String.raw`\\\(\^${mouth}\^\)/`)

と、リテラルを使った表現に近くなります。

おまけ:メタ文字のエスケープ

変数の部分に外部からの入力を使う場合、メタ文字が入っていると正規表現全体の動作に関わってしまいます。これを防ぐために以下の関数を用意します。

正規表現 - JavaScript | MDN

function escapeRegExp(string) {
  return ("" + string).replace(/[.*+?^=!:${}()|[\]\/\\]/g, "\\$&");
}

これを入力された文字列に適用します。

mouth = prompt("好きな口を入力してください") || "o"
re = new RegExp(String.raw`\\\(\^${escapeRegExp(mouth)}\^\)/`)

テンプレートリテラルも囲めば\(^o^)/をわかりやすく出来ますが、場合によっては正規表現である意味がなくなります。

mouth = prompt("好きな口を入力してください") || "o"
re = new RegExp(escapeRegExp(String.raw`\(^${mouth}^)/`))
26
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
26
18