JavaScriptで複数置換をスマートにやりたい

2022/05/24
サムネイル画像

JavaScriptで複数パターンの置換をまとめてやりたいと思っていたとき、なかなかしっくりくる方法がありませんでした。自分でいろいろ試してみた結果、お気に入りの方法を見つけたのでご紹介します。

やりたかったこと

文字列を操作するとき、複数の文字列をまとめて置換したい…というシチュエーションがあると思います。例えば、

・#\/

という文字列で、記号を置換によりエンコードしたいというとき。

この場合、replaceメソッドを用いた通常の方法だと以下のようになります。

let str = '・#\/';
str = str.replace(/・/g, '%E3%83%BB').replace(/#/g, '%23').replace(/\//g, '%2F').replace(/\\/g, '%5C');

※gは対象パターンの全置換のためのオプションフラグ。

なんだかreplaceがたくさんひっついていますね。これはメソッドチェーンといって、繰り返しreplaceを適用することによって複数置換する…という方法です。

ですが、求めていたのはこれじゃない。置換パターンが2, 3個ならまだ良いですが、ある程度多くのパターンをまとめて置換したいという場合、replaceを繋げまくるのは大変です。しかも見た目もよろしくない。

ということで、別の方法を考えてみました。

スマートに複数置換

配列とループを利用して、複数パターンの置換を実現します。以下のような形です。

let str = "・#\/"
const keys = [/・/g, /#/g, /\//g, /\\/g];
const reps = ["%E3%83%BB", "%23", "%2F", "%5C"];
for (let i = 0; i < keys.length; i++) {
  str = str.replace(keys[i], reps[i]);
}

変換対象文字列をkeys、置換文字列をrepsとして、それぞれ配列に格納しておきます。そしてkeysの長さ分forループを回し、対応する位置の文字列を置き換えていきます。

ループが回るたびにstrが上書きされ、結果として複数パターンの置換が実現できるというわけです。メソッドチェーンを疑似的に適用した形になっています。

通常のメソッドチェーンと比べて少し行数は増えてしまいますが、置換パターンを配列で一元管理できるので扱いやすく、個人的には気に入っています。

注意点:置換の順番に注意

通常の方法と今回の方法どちらにもいえることですが、置換をする際には順番に注意が必要です。

例えば、先ほどの文字列で「・」が実体参照コード「&#12539;」として表示されていた場合、「#」の置換を先にすると思い通りの結果が得られません。

let str = '&#12539;#\/';
str = str.replace(/#/g, '%23').replace(/&#12539;/g, '%E3%83%BB').replace(/\//g, '%2F').replace(/\\/g, '%5C');

上の例では「#」の置換が先に適用されてしまい、うまく「・」部分を変換できなくなります。期待通りの動作にするには、置換を入れ替える必要があります。

コメントはまだありません