こちらのアプリ↓を作るときにJavaScriptのreplace()メソッド周りで詰まったので、忘備録を書きます。
replace()メソッドの基本的な使い方
まず、JavaScriptのreplace()メソッドは、置換したいテキストに対して
replace(’置換したい文字列’,’置換後の文字列’)
みたいに使います。
記述例
たとえばこんな感じ。
//元のテキスト
let text = 'おはようございます。今日はいい天気ですね。';
//replace()を使って「おはようございます」を「こんにちは」に置換する。
text = text.replace('おはようございます', 'こんにちは');
//console.logで出力を確認する。
console.log(text);
//結果:こんにちは。今日はいい天気ですね。
「おはようございます」が「こんにちは」置換されるはずです。
しかし、一か所しか置換されない!
しかし、上記の書き方だと少し問題があります。
一か所しか置換されないのです。
たとえば、
//元のテキスト
let text = 'しんぶんし。下から読んでも、しんぶんし。';
元のテキストに置換したい文字列が2か所以上ある場合…
let text = 'しんぶんし。下から読んでも、しんぶんし。';
text = text.replace('しんぶんし', 'イカとカイ');
console.log(text);
//結果:イカとカイ。下から読んでも、しんぶんし。
先ほどの書き方だと、最初の「しんぶんし」しか置換されません。
どちらの「しんぶんし」も「イカとカイ」に置換したい!
//gで囲む。
結論から言えば、「正規表現のgオプション」を使うと解決します。
やり方は、置換したい文字列を「‘ ‘」の代わりに「/ /g」で囲むだけ。
let text = 'しんぶんし。下から読んでも、しんぶんし。';
text = text.replace(/しんぶんし/g, 'イカとカイ');
console.log(text);
//結果:イカとカイ。下から読んでも、イカとカイ。
これで全ての「しんぶんし」が「イカとカイ」に置換できました!
replaceAll()でもできる
ちなみに、近年追加されたreplaceAll()メソッドでも上手くいきます。
let text = 'しんぶんし。下から読んでも、しんぶんし。';
text = text.replaceAll('しんぶんし', 'イカとカイ');
console.log(text);
//結果:イカとカイ。下から読んでも、イカとカイ。
※対応するブラウザには注意
変数で置換したい文字列を指定したい。
さて。
ここまでは、「置換したい文字列」も「置換後の文字列」も直接replace()メソッドの中に文字列を書き込んでいました。
replace(/置換したい文字列/g, ’置換後の文字列’)
これを変数で指定したくなってきます。
しかし…
let text = 'しんぶんし。下から読んでも、しんぶんし。';
let before_word = 'しんぶんし'
let after_word = 'イカとカイ'
text = text.replace(/before_word/g, after_word);
こんな感じ↑に馬鹿正直に変数に置き換えて書いてもダメです。
置換したい文字列が”before_wordそのもの“になるので、上手くいきません。
では、どうするか。
RegExp オブジェクトのコンストラクター関数を呼び出す。
コンストラクター関数というやつを使います。
つまり、こうやって書けばOK!
text = text.replace(new RegExp(before_word, "g"), after_word);
これで
//元のテキスト
let text = 'しんぶんし。下から読んでも、しんぶんし。';
let before_word = 'しんぶんし'
let after_word = 'イカとカイ'
text = text.replace(new RegExp(before_word, "g"), after_word);
console.log(text);
//結果:イカとカイ。下から読んでも、イカとカイ。
変数を使ってreplace()メソッドを使えました!
しかし…
これで大体上手くいくはずです。
しかし、メタ文字(正規表現で使用する特殊文字)が誤った形で「置換したい文字列」に含まれていた場合にエラーになります。
たとえば、半角の括弧 → (だけとかです。
対策1:先に正規表現でエスケープが必要な文字を置換する。
対策の一つ目は最初から正規表現を封じる方法。
やり方は、replace()メソッドをもう一つ使います。
before_word = before_word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
前もって正規表現をエスケープさせてエラーになるのを防ぐわけです。
let text = 'しんぶんし。下から読んでも、しんぶんし。';
let before_word = '(しんぶんし'
let after_word = 'イカとカイ'
before_word = before_word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
text = text.replace(new RegExp(before_word, "g"), after_word);
console.log(text);
//結果:しんぶんし。下から読んでも、しんぶんし。
つまりこうです。
これで「(しんぶんし」の「(」でエラーにならずに済みます。
対策2:エラーになったときだけ対応する。
でも、できれば正規表現も使いたいよ…。
そんな時は、try-catch文を使ってみます。
try {
text = text.replace(new RegExp(before_word, "g"), after_word);
} catch (e) {
before_word = before_word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
text = text.replace(new RegExp(before_word, "g"), after_word);
};
try{}の中身が通常の処理、catch(e){}の中身がエラー時の処理です。
エラー時だけ正規表現をエスケープさせるわけです。
let text = 'しんぶんし。下から読んでも、しんぶんし。';
let before_word = '(しん.ん.)'
let after_word = '!!$1!!'
try {
text = text.replace(new RegExp(before_word, "g"), after_word);
} catch (e) {
before_word = before_word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
text = text.replace(new RegExp(before_word, "g"), after_word);
};
console.log(text);
//結果:!!しんぶんし!!。下から読んでも、!!しんぶんし!!。
これで正規表現を使った置換もエラーを心配せずに実行できます。(たぶん)
ちなみに…
上記のコードの$1は、置換前の( )の中身がそのまま置換後へ反映される書き方です。
また、もし置換前に( )で囲まれた文字列が2つあれば、左から$1、$2と書けばそれぞれ反映されます。
replace('(しん)ぶん(し)', '!!$1!!$2')
//結果:!!しん!!し
配列を使って一気に置換したいなぁ…
最後に配列を作って、一気に置換をする方法を紹介します。
まず、「置換したい文字列」と「置換後の文字列」を入れる2次元配列を作ります。
let replacement_words = [
['(しん.ん.)', '!!$1!!'],
['しんぶんし', 'イカとカイ'],
['下から読んでも', 'とてもおいしい'],
];
あとは、配列の長さを.lengthで取得してfor文を回せばOKです。
for (let i = 0; i < replacement_words.length; i++) {
text = text
.replace(new RegExp(replacement_words[i][0], "g"), replacement_words[i][1]);
};
これで、配列の長さが変わっても(文字列を追加や削除をしても)大丈夫です。
まとめ
ここまでの内容をまとめたコードです。
//元のテキスト
let text = 'しんぶんし。下から読んでも、しんぶんし。';
//置換したいテキストの2次元配列
let replacement_words = [
['(しん.ん.)', '!!$1!!'],
['しんぶんし', 'イカとカイ'],
['下から読んでも', 'とてもおいしい'],
];
try {
for (let i = 0; i < replacement_words.length; i++) {
text = text
.replace(new RegExp(replacement_words[i][0], "g"), replacement_words[i][1]);
};
} catch (e) {
//エラー時の処理
for (let i = 0; i < replacement_words.length; i++) {
replacement_words[i][0] = replacement_words[i][0]
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
text = text
.replace(new RegExp(replacement_words[i][0], "g"), replacement_words[i][1]);
};
};
console.log(text);
//結果:!!イカとカイ!!。とてもおいしい、!!イカとカイ!!。
さいごに
というわけで、JavaScriptのreplace()メソッドの使い方と応用の忘備録でした。
では!(๑˃̵ᴗ˂̵)و