MENU

JavaScript正規表現

【JavaScript】 replace()の使い方 単純な置換と正規表現での置換

更新日:2020/04/10

 

JavaScriptで文字列の置換をおこなう場合、ほとんどのケースでreplace()を使用できます。
単純な置換から正規表現を使用しての置換、さらにはコールバック関数を使用して置換する内容を細かく制御できるのだから万能といっていい。

 

だが初めて使う人は、少し戸惑うと思う。

 

そこで今回は、JavaScriptのreplace()メソッドについて自分なりにまとめてみる。

 

単純な置換

 

単純に文字列を置換したい場合、次のようにreplaceを使用すればいい。

 

構文:  元になる文字列.replace( 置き換え前の文字列 , 置き換え後の文字列 )

 

メソッドは結果として、置換後の文字列を返す。

 

単一の置換

 

置き換え前の文字列をテキストで指定した場合、最初に出てきたものだけ置換される。

 

例:最初の一つだけ置換

const text = "abcdefg abcdefg";
const result = text.replace( "def" , "---");
console.log( result); // abc---g abcdefg

 

全て置換

 

全て置換したい場合、次のように正規表現に書き換えればいい。

 

"置き換え前の文字列"      /置き換え前の文字列/g

 

例:全て置換

const text = "abcdefg abcdefg";
const result = text.replace( /def/g , "---"); // 正規表現部分に""はつけない
console.log( result); // abc---g abc---g

 

JavaScriptの正規表現については、こちらを参照してください。
【JavaScript】 正規表現まとめメモ

 

大文字小文字を区別しないで置換

 

大文字と小文字を区別しないで置換する場合、iオプションを指定すればいい。

 

"置き換え前の文字列"      /置き換え前の文字列/gi
※gは任意

 

例:大文字と小文字を区別しないで全て置換

const text = "abcdefg abcDeFg";
const result = text.replace( /def/gi , "---");
console.log( result); // abc---g abc---g

 

後ろから検索して置換

 

文字列の最後から検索して置換したい場合は、次のように正規表現を組み立てる。

 

"置き換え前の文字列"      /(.*)置き換え前の文字列/

 

置換後の文字列には、次のように記述する。

 

"置き換え後の文字列"      "$1置き換え後の文字列"

 

const data = "今日東京は快晴です!しかし残念ながら明日は快晴となるでしょう。";
const result = data.replace( /(.*)快晴/ , "$1豪雨" );
console.log( result ); // 今日東京は快晴です!しかし残念ながら明日は豪雨となるでしょう。

 

 

 

複数の文字列を置換

 

複数の文字列を置換したい場合は、replace()をメソッドチェーンで連結します。

 

例:複数の文字列を置換

const text = "abcdefg abcdefg";
const result = text.replace( /def/g , "DEF").replace( /ab/g , "AB");
console.log( result );    // ABcDEFg ABcDEFg

検索結果を置換文字に反映

 

置き換え後の文字列に特殊な記号を使用することで、置き換え前の文字列を反映した置換をおこなえます。

 

const text = "abcdefg abcdefg";
const result = text.replace( /def/g , "[$&]");
console.log( result); // abc[def]g abc[def]g

 

上の例で $&は、置き換え前の文字列つまりdefです。
その文字列を[ ]で囲ったもので置換しています。

 

置換パターンには、次のようなものがあります。

 

 

置換パターン
元になる文字列:"abcdefg abcdefg"
パターン 説明 結果
$& 置き換え対象の文字列 text.replace( /def/g , "[$&]") abc[def]g abc[def]g
$` 置き換え対象の文字列よりの部分 text.replace( /def/g , "[$`]") abc[abc]g abc[abcdefg abc]g
$' 置き換え対象の文字列より後ろの部分 text.replace( /def/g , "[$']") abc[g abcdefg]g abc[g]g
$n キャプチャされた文字列(nは1~) text.replace( /def/g , "[$2$1]") abc[efd]g abc[efd]g
$$ $を文字として使用 text.replace( /def/g , "[$$]") abc[$]g abc[$]g

コールバック関数で置換文字を操作

 

replace()メソッドの第二引数には、置き換え後の文字列の代わりにコールバック関数を指定することができます。

 

構文:  元になる文字列.replace( 置き換え前の文字列 , コールバック関数 )

 

コールバック関数の構文:

 

     関数式     function ( p0 [, p1 ... ] , index ,  input){ }
     アロー関数式     ( p0 [, p1 ... ] , index ,  input) => { }

 

     p0 : マッチした文字列
     p1~ : 正規表現でキャプチャした文字列。キャプチャされる数により変化する
     index : マッチした文字列の位置(0~)
     input : 元になる文字列

 

     リターン値 : 置き換え後の文字列

 

const text = "abc1defg abc2defg";
const result = text.replace( /(c\d)(def)/g , ( p0 , p1 , p2 )=>{
            return " ★ [" + p0 + "] → [" + p1 + p2.toUpperCase() + "] ★ ";
});
console.log( result); // ab ★ [c1def] → [c1DEF] ★ g ab ★ [c2def] → [c2DEF] ★ g

 

※p1~は、置き換え前の文字列として与えた正規表現のパターンによって増減します。
そのためindexやinputを使用したいときは、正確な個数を指定する必要があります。

 

ただし次のようにレスト構文を使用することで、正確な指定をしなくても、マッチした文字列の位置や元になる文字列を取得することができます。

 

レスト構文で引数を配列に集約

const result = text.replace( /(c\d)(def)/g , ( ...arg )=>{
            const length = arg.length;
            const index = arg[length - 2];
            const input = arg[length - 1];
            return "index:" + index + " input:" + input;
        });

 

参考:【JavaScript】 コード中の「...」は意味があった スプレッド/レスト構文

置換例

 

改行を統一

 

改行文字『\r』『\r\n』を『\n』に統一

 

text.replace( /\r|\r\n/g ,  "\n" )
または
text.replace( /\r\n?/g ,  "\n" )

 

備考:?は0回または1回の繰り返しを意味する。つまり\r\n?は『\r』『\r\n』にマッチする。

 

改行を<br>に変更

 

改行文字『\r』『\r\n』『\n』を『<br>』に置換

 

text.replace( /\r|\n|\r\n/g ,  "<br>" )

 

改行を削除

 

改行文字『\r』『\r\n』『\n』を削除

 

text.replace( /\r|\n|\r\n/g ,  "<>" )

 

全角半角スペースを統一

 

半角スペース → 全角スペース

 

text.replace( / /g ,  " " )

 

全角スペース → 半角スペース

 

text.replace( / /g ,  " " )

 

半角全角英数記号を統一

 

対象文字:!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

 

半角英数記号 → 全角英数記号

 

const baseValue = "!".charCodeAt(0) - "!".charCodeAt(0);

 

const result = data.replace( /[!-~]/g ,
            (v) => String.fromCharCode(v.charCodeAt(0) + baseValue)
        );

数字のみ:/[0-9]/g
アルファベットのみ:/[A-Z]/g ・/[a-z]/g ・/[A-Za-z]/g

 

 

全角英数記号 → 半角英数記号

 

const baseValue = "!".charCodeAt(0) - "!".charCodeAt(0);

 

const result = data2.replace(/[!-~]/g,
            (v) => String.fromCharCode(v.charCodeAt(0) - baseValue)
        );

数字のみ:/[0-9]/g
アルファベットのみ:/[A-Z]/g ・/[a-z]/g ・/[A-Za-z]/g

 

半角全角カタカナ・ひらがな変換

 

半角全角のコードの並び順が一定ではないので、変換用の配列マップを作成する。

 

const kanaZenkaku = [
            "ア","イ","ウ","エ","オ","カ","キ","ク","ケ","コ","サ","シ","ス","セ","ソ",
            "タ","チ","ツ","テ","ト","ナ","ニ","ヌ","ネ","ノ","ハ","ヒ","フ","ヘ","ホ",
            "マ","ミ","ム","メ","モ","ヤ","ユ","ヨ","ラ","リ","ル","レ","ロ",
            "ワ","ヰ","ヱ","ヲ","ン",
            "ガ","ギ","グ","ゲ","ゴ","ザ","ジ","ズ","ゼ","ゾ","ダ","ヂ","ヅ","デ","ド",
            "バ","ビ","ブ","ベ","ボ","パ","ピ","プ","ペ","ポ",
            "ァ","ィ","ゥ","ェ","ォ","ャ","ュ","ョ","ッ"
];
kanaZenkaku.reg = new RegExp( "(" + kanaZenkaku.join("|") + ")" , "g");

 

const kanaHankaku = [
            "ア","イ","ウ","エ","オ","カ","キ","ク","ケ","コ","サ","シ","ス","セ","ソ",
            "タ","チ","ツ","テ","ト", "ナ","ニ","ヌ","ネ","ノ","ハ","ヒ","フ","ヘ","ホ",
            "マ","ミ","ム","メ","モ","ヤ","ユ","ヨ","ラ","リ","ル","レ","ロ",
            "ワ","イ","エ","ヲ","ン",
            "ガ","ギ","グ","ゲ","ゴ","ザ","ジ","ズ","ゼ","ゾ","ダ","ヂ","ヅ","デ","ド",
            "バ","ビ","ブ","ベ","ボ","パ","ピ","プ","ペ","ポ",
            "ァ","ィ","ゥ","ェ","ォ","ャ","ュ","ョ","ッ"
        ];
kanaHankaku.reg = new RegExp( "(" + kanaHankaku.join("|") + ")" , "g");

 

const hiragana = [
            "あ","い","う","え","お","か","き","く","け","こ","さ","し","す","せ","そ",
            "た","ち","つ","て","と", "な","に","ぬ","ね","の","は","ひ","ふ","へ","ほ","ま",
            "み","む","め","も","や","ゆ","よ", "ら","り","る","れ","ろ",
            "わ","ヰ","ゑ","を","ん",
            "が","ぎ","ぐ","げ","ご","ざ","じ","ず","ぜ","ぞ","だ","ぢ","づ","で","ど",
            "ば","び","ぶ","べ","ぼ","ぱ","ぴ","ぷ","ぺ","ぽ",
            "ぁ","ぃ","ぅ","ぇ","ぉ","ゃ","ゅ","ょ","っ"
        ];
hiragana.reg = new RegExp( "(" + hiragana.join("|") + ")" , "g");

※各配列のregプロパティは、検索用の正規表現オブジェクト。

 

次のコードは、変換用の共通関数。

 

function kanaConv( text , formArray , toArray ) {
            return text.replace(formArray.reg,
                (v) => {
                    return toArray[ formArray.indexOf( v ) ];
                }
            );
}

 

半角カタカナ → 全角カタカナ

 

const text = "アイウエオカキクケコ";
const result = kanaConv( text , kanaHankaku , kanaZenkaku  );
console.log( result ); // アイウエオカクキケコ

 

全角カタカナ → 半角カタカナ

 

const text = "アイウエオカクキケコ";
const result = kanaConv( text , kanaZenkaku , kanaHankaku  );
console.log( result ); // アイウエオカキクケコ

 

半角カタカナ → ひらがな

 

const text = "アイウエオカキクケコ";
const result = kanaConv( text , kanaHankaku , hiragana   );
console.log( result ); // あいうえおかきくけこ

 

全角カタカナ → ひらがな

 

const text = "アイウエオカクキケコ";
const result = kanaConv( text , kanaHankaku , hiragana   );
console.log( result ); // あいうえおかきくけこ

 

※ひらがなから半角/全角カタカナへの変換も同様に行える。

 

 

数値を3桁毎にカンマ(,)で区切る

 

文字列中の数値を3桁毎にカンマで区切る。

 

const text ="1個3000.25円のリンゴを20000個購入した。総額60005000円だ。";
const result = text.replace(/\d\d\d\d+/g, // (1)
            ( val ) =>{                
                    return  val.replace(/(\d)(?=(\d\d\d)+$)/g, "$1,"); // (2)
            }
        );
console.log( result ); // 1個3,000.25円のリンゴを20,000個購入した。総額60,005,000円だ。

 

簡単な解説

 

(1) /\d\d\d\d+/g : 4桁以上の数値に一致(小数部分は含まない)

 

(2) /(\d)(?=(\d\d\d)+$)/g :
     一文字の数値の後に3桁の数値の組が複数続く場合一致し、最初の一文字のみ取得
      例: 1 234 567 890   例: 1 234 など

 

     (\d) 数値一文字に一致。$1にキャプチャされる。
     y(?=x) yの後にxが続く場合yがマッチする。
               xは一致対象にならない。
               ここでのxは(\d\d\d)+$
     (\d\d\d)+ 3桁の数値が1回以上繰り返される。
     $ 文字列の最後。

 

     一度のマッチで取得するのは最初の(\d)の部分。
     2回目は(\d)の次の文字からマッチングがおこなわれる。

 

     数値に小数点を含む場合は、/(\d)(?=(\d\d\d)+(?!\d))/とすればよい。

まとめ

 

replace()は基本的に最初に検索された文字列のみ置換される。
しかし実際に現場では、全て変換したいというケースが多い。
初めて使う人は、大いに悩むメソッドである。

 

正規表現も頑張って覚えないといけないかもしれない…

記事の内容について

 

こんにちはけーちゃんです。
説明するのって難しいですね。


「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。

そんなときは、ご意見もらえたら嬉しいです。

ご意見はこちら。
https://affi-sapo-sv.com/info.php

【お願い】

お願い

■このページのURL


■このページのタイトル


■リンクタグ