『replace()』は、文字列の置換を行う関数です。
基本的な使い方は、下記の通りです。
var text = "abcabc"; var result = text.replace(/a/g, "1"); // "abcabc"内の"a"を最後まで検索して"1"に置換する // 結果:resultは"1bc1bc"になる
『replace()』の第1引数の『/a/g』は、検索する文字列を正規表現で表したものです。
- 正規表現では、検索する文字列を『/(スラッシュ)』で囲みます。
- 末尾の『g』は、最後まで探すというフラグです。
フラグには下表のようなものがあります。フラグ 意味 g 1個目だけでなく最後まで検索します。 i 検索の際に大文字と小文字を区別しません。 m 複数行に渡って検索します。
*また『text.replace("a", "1");』のように通常の文字列で検索すると1個目しか置換されません。var text = "abcabc"; var result = text.replace(/a/, "1"); // resultは"1bcabc"になる(1個目だけ置換) var result = text.replace("a", "1"); // resultは"1bcabc"になる(1個目だけ置換)
正規表現を使う利点は、"文字のパターン"で検索出来ることです。
例えば、『"'abc','de',f"』で'abc'と'de'を1に変えたい場合、『'(シングルコーテーション)で囲まれている文字列』というパターンで検索することで、文字の種類、長さが異なる'abc'と'de'を一度に置換することが出来ます。実際にどうやるかは後述しています。
また、『replace()』の第2引数にコールバック関数を指定すると、見つかった文字ごとに違う処理を行うことが出来ます。
上記の例を含めて『replace()』の様々な使い方をまとめました。目次
使用環境
私が使用している環境です。
- Mac OS X El Capitan Version 10.11.4
- ブラウザ:Google Chrome Version 50.0.2661.102 (64-bit)
記事内のコードは、google ドキュメントのスクリプトエディタで動作確認しました。
正規表現でパターン検索
メタ文字
正規表現ではメタ文字を使って文字のパターンを表現します。
メタ文字とは正規表現において特殊な意味を持つ文字のことです。- 例:メタ文字を使った正規表現
var text = "'abc','de',f"; var result = text.replace(/'.*?'/g, "1"); // 『'.*?'』の部分が正規表現 // 結果:resultは"1,1,f"になる // 文字の種類や長さが異なる'abc'と'de'を一度に置換出来ている
2行目の『'.*?'』は『'(シングルコーテーション)で囲まれている文字列』という文字のパターンを表した正規表現です。パターンで検索するので、文字の種類や長さが異なっても一度に置換出来ます。
ここで使用したメタ文字とその意味です。メタ文字 意味 .(ピリオド) 任意の1文字 *?(アスタリスク、クエスチョン) 直前の文字が0文字以上続くもので、
当てはまる中で最短のもの(最短一致)
*最短一致については後述
『最初に'(シングルコーテーション)があり、
次に、任意の文字が0文字以上続いて、
最後に'(シングルコーテーション)がある文字列
の中で最短のもの』
最短一致と最長一致
- 例:『'abc','de',f』から『'(シングルコーテーション)で囲まれている文字列』を置換
『*?』:最短一致(当てはまる中で最短のもの)を検索します。
『*』:最長一致(当てはまる中で最長のもの)を検索します。var text = "'abc','de',f"; var result = text.replace(/'.*?'/g, "1"); // 最短一致、結果:resultは"1,1,f"になる var result = text.replace(/'.*'/g, "1"); // 最長一致、結果:resultは"1,f"になる
『'a』から『'(シングルコーテーション)で囲まれている文字列』を探すと、『'abc'』、『'abc','』、『'abc','de'』の3パターン見つかります。
この中で『'abc'』が最短一致、『'abc','de'』が最長一致となります。
メタ文字自身を検索するには『\(バックスラッシュ)』を付ける
メタ文字を通常の文字として検索したい場合は、その文字の前に『\(バックスラッシュ)』を付けます。
- 例:『()』で囲まれた文字を置換
var text = "abc,(de),f"; // 成功例 var result = text.replace(/\(.*?\)/g, "1"); // バックスラッシュを付ける // 『(』と『)』を通常の文字として処理される // 結果:resultは"abc,1,f"になる // 失敗例 var result = text.replace(/(.*?)/g, "1"); // バックスラッシュを付けない // 『(』と『)』をメタ文字として処理される // 結果:resultは"1a1b1c1,1(1d1e1)1,1f1"になる
『(』と『)』はそのままだとメタ文字として処理されます。
それぞれ『\(バックスラッシュ)』を付けて『\(』と『\)』とすることで通常の文字として検索されます。
『\』は、次の1文字はメタ文字じゃないよ、という意味です。
『\』は、キーボードの『option + ¥』で入力出来ます。
見つかった文字列を置換に使用する方法
"パターン検索で見つかった文字列"を置換に使用する方法です。
例:"abc,de,f" → "<b>abc</b>,<b>de</b>,f"
検索して"abc"が見つかったら"<b>abc</b>"、"de"が見つかったら"<b>de</b">のように、"見つかった文字列"を『<b></b>』で囲んだ文字列に置換します。
下記のような方法があります。『$&』で見つかった文字列を置換後に使用する
- 例:見つかった文字列を<b>〜</b>で囲む置換
var text = "abc,de,f"; var result = text.replace(/abc|de/g, "<b>$&</b>"); // 結果:resultは<b>abc</b>,<b>de</b>,f
『/abc|de/g』により、"abc"または"de"を検索しています。
『$&』の部分は、"abc"が見つかった時は"abc"に置換され、"de"が見つかった時は"de"に置換されます。
『$1、$2、・・・』で見つかった文字列の一部に番号を付けて使用する
- 例:見つかった文字列を<b>〜</b>で囲む置換
var text = "abc,de,f"; var result = text.replace(/(abc),(de)/g, "<b>$1</b>,<i>$2</i>"); // 結果:resultは"<b>abc</b>,<i>de</i>,f"になる
『/(abc),(de)/g』により『"abc,de"』を検索しています。
『(』と『)』はメタ文字です。置換後に使いたい部分を『()』で囲みます。
『$1』は、1個目のカッコ内の『"abc"』を呼び出します。
『$2』は、2個目のカッコ内の『"de"』を呼び出します。
コールバック関数『function()とarguments』を使用する
コールバック関数を使うとさらに複雑な置換が可能です。
『replace()』の第2引数に『置換後の文字列』の替わりに、コールバック関数の『function(){}』を渡します。- 例:小文字を大文字に置換する
var text = "'abc','de',f"; var result = text.replace(/'.*?'/g, function(){ // 第2引数に関数を渡す return arguments[0].toUpperCase(); // 見つかった文字列を大文字に変換して返す }); // 結果:resultは"'ABC','DE',f"になる
『arguments[0]』がいきなり出てきますが、決まりごとです。
検索条件に合った文字列が見つかるたびにコールバック関数が実行され、『arguments[0]』に見つかった文字列が代入されます。
コールバック関数内で文字列を大文字に加工して『return』で返すと、それが置換後の文字列となります。
『arguments』(検索結果)で条件分岐
『arguments[0]』だけでなく『arguments』配列には検索条件に応じて検索結果が代入されます。『arguments』配列のサイズは、下表のように正規表現に含まれる『()』の数で変わります。
- 例:『''』には囲まれていない『<>』を『[]』に置換
var text = "'<abc>',<de>,f"; var result = text.replace(/'(.*?)'|<(.*?)>/g, // 『|』はorを示すメタ文字 function(){ // '<abc>'が見つかった時のargumentsの中身 // arguments[0]:検索条件で見つかった文字列、今回は"'<abc>'" // arguments[1]:検索条件の1個目の()に該当する文字列、今回は"<abc>" // arguments[2]:検索条件の2個目の()に該当する文字列、今回は該当なしなのでundefined // arguments[3]:見つかった文字列の先頭の位置(0始まり)、今回は0 // arguments[4]:検索の対象の文字列、今回は"'<abc>',<de>,f" // <de>が見つかった時のargumentsの中身 // arguments[0]:検索条件で見つかった文字列、今回は"<de>" // arguments[1]:検索条件の1個目の()に該当する文字列、今回は該当なしなのでundefined // arguments[2]:検索条件の2個目の()該当する文字列、今回はde // arguments[3]:見つかった文字列の先頭の位置(0始まり)、今回は8 // arguments[4]:検索の対象の文字列、今回は"'<abc>',<de>,f" if(!arguments[1] && arguments[2]) { // ''に囲まれず、<>に囲まれた文字列 return "[" + arguments[2] + "]"; } else { return arguments[0] } }); // 結果:resultは"'<abc>',[de],f"になる
『/'(.*?)'|<(.*?)>/g』により『''で囲まれた文字列』または『<>で囲まれた文字列』を検索します。
『arguments[0]』には『検索条件で見つかった文字列』が代入されます。
『arguments[1]』には『検索条件内の1番目の()に該当する文字列』=『''で囲まれた文字列』が代入されます。
『arguments[2]』には『検索条件内の2番目の()に該当する文字列』=『<>で囲まれた文字列』が代入されます。
これを利用して『 if(!arguments[1] && arguments[2])』によって『''に囲まれず、<>に囲まれた文字列』の場合だけ、『[]』で文字列を囲む置換を行っています。
arguments[0] 見つかった文字列 arguments[1] 正規表現の1個目の()内に該当する文字列 arguments[n] 正規表現のn個目の()内に該当する文字列 arguments[arguments.length-2] 見つかった文字列の先頭の位置、0始まり arguments[arguments.length-1] 検索の対象の文字列 正規表現の『()』の囲み方の違いについて
上記の例で、カッコの位置が『(<.*?>)』の場合は『arguments[2]』は『
』となります。
カッコの位置が『<(.*?)>』の場合は『arguments[2]』は『de』となり、『<>』の中身を取得できます。動的に正規表現を作成
『new RegExp()』を使うと通常の文字列から正規表現を動的に作成できます。
『new RegExp("<りんご>", 'g')』は『/<りんご>/g』と同じ意味です。- "apple"→"りんご"、"grape"→"ぶどう"、"peach"→ "もも"に置換する
var result = "<apple>,<grape>,<peach>"; var arrReplaceData = [ ["apple", "りんご"], ["grape", "ぶどう"], ["peach", "もも"] ]; for(var i = 0; i < arrReplaceData.length; i++){ var replaceData = arrReplaceData[i]; result = result.replace( new RegExp("<" + replaceData[0] + ">", 'g'), function() { return replaceData[1]; }); } // 結果:resultは"りんご,ぶどう,もも"になる
『検索の文字列』と『置換後の文字列』のペアの配列を作成し、forループ内で動的に正規表現を作成して各ペアの置換を実行しています。
『\(バックスラッシュ)に注意
動的に正規表現を作成する場合、『new RegExp()』に渡す文字列の『\』を2重にする必要があります。
- 例:『\』を含む文字列から正規表現を動的に作成する
『\b』は単語の区切りを意味するメタ文字です。
『grape』を検索する際に『grapefruit』が検索されないようにするには『/grape\b/g』と書きます。
『new RegExp()』に渡す文字列に『\』が含まれるので『\』を下記のように2重にして渡します。var result = "apple,grapefruit,peach"; var arrReplaceData = [ ["apple\\b", "りんご"], ["grape\\b", "ぶどう"], ["peach\\b", "もも"] ]; for(var i = 0; i < arrReplaceData.length; i++){ var replaceData = arrReplaceData[i]; result = result.replace( new RegExp(replaceData[0], 'g'), function() { return replaceData[1]; }); } // 結果:resultは"りんご,grapefruit,もも"になる
var result = "abc\\tde"; var replaceData = ["\\\\t","タブ"]; result = result.replace( new RegExp(replaceData[0], 'g'), function() { return replaceData[1]; }); // 結果:resultは"abcタブde"になる
バックスラッシュだらけです。