JavaScript Tips | 文字列ユーティリティ:検索・置換 - 正規表現置換

JavaScript JavaScript
スポンサーリンク

「正規表現置換」ができると何が嬉しいのか

まずイメージからいきます。
普通の置換は「この文字列を、この文字列に変える」だけです。

"2026/02/19" の "/" を "-" に変える
"foo foo foo" の "foo" を "bar" に変える

でも業務では、もっと“パターン”で置き換えたいことがたくさんあります。

数字だけを全部消したい。
連続する空白を1個にまとめたい。
電話番号の「数字だけ」を抜き出してフォーマットし直したい。

こういう「形にルールがあるものをまとめて置き換える」ときに使うのが、正規表現置換です。


JavaScript の replace と正規表現の基本

replace は「文字列」も「正規表現」も受け取れる

String.prototype.replace は、第一引数に
文字列だけでなく「正規表現」も渡せます。

const s = "abc123def456";

s.replace("123", "X");      // "abcXdef456"(最初の1箇所だけ)
s.replace(/\d+/g, "X");     // "abcXdefX"(数字のまとまりを全部 X に)
JavaScript

/\d+/g が正規表現です。

\d は「数字1文字」
+ は「1回以上の繰り返し」
g は「global(全体)」=全部対象にするフラグ

つまり「数字が1文字以上続くところを全部」という意味になります。

ここでのポイントは、

文字列 "123" を指定すると「その文字列に完全一致したところだけ」。
正規表現 /\d+/g を指定すると「数字のまとまり全部」。

というふうに、「何を検索対象にするか」をもっと柔軟に書ける、ということです。


正規表現置換ユーティリティの基本形

「パターン」と「置換後」を受け取る関数

まずは、素直なラッパーから作ってみます。

function replaceAllRegex(text, pattern, replacement) {
  if (text == null) return "";
  if (!(pattern instanceof RegExp)) {
    throw new Error("pattern は RegExp である必要があります");
  }

  const s = String(text);

  // g フラグが付いていない場合は付け直す
  const flags = pattern.flags.includes("g")
    ? pattern.flags
    : pattern.flags + "g";

  const regex = new RegExp(pattern.source, flags);

  return s.replace(regex, replacement);
}
JavaScript

重要なポイントを噛み砕きます。

text が null / undefined でも落ちないようにしている。
pattern がちゃんと RegExp かどうかをチェックしている。
pattern.flags からフラグ(ig など)を取り出している。
g が付いていなければ足して、新しい正規表現を作り直している。
最後は replace に渡しているだけ。

これで、「正規表現でマッチしたところを全部置き換える」関数になります。


具体例で「正規表現置換」の威力を感じる

数字だけを全部消す

replaceAllRegex("abc123def456", /\d+/g, ""); // "abcdef"
JavaScript

「数字が1文字以上続くところ」を全部空文字に置き換えています。
ログから ID を消したり、マスクしたりするときに使えます。

連続する空白を1個にまとめる

replaceAllRegex("a   b    c", /\s+/g, " "); // "a b c"
JavaScript

\s は「空白文字(スペース・タブ・改行など)」です。
\s+ で「1文字以上の空白」を表し、それを " "(半角スペース1個)に置き換えています。

入力値の整形や、CSV の前処理などでよく使うパターンです。

数字だけを抜き出してフォーマットする(電話番号)

正規表現置換は、「消す」だけでなく「整える」にも使えます。

function normalizePhone(phone) {
  if (phone == null) return "";

  // 数字以外を全部消す
  const digits = String(phone).replace(/\D+/g, "");

  // 例: 09012345678 → 090-1234-5678 っぽく整形(ざっくり例)
  return digits.replace(/(\d{3})(\d{4})(\d{4})/, "$1-$2-$3");
}

normalizePhone("090-1234-5678");   // "090-1234-5678"
normalizePhone("090 1234 5678");   // "090-1234-5678"
normalizePhone("090-1234-5678(代表)"); // "090-1234-5678"
JavaScript

ここでは二段階で正規表現置換を使っています。

\D+ で「数字以外」を全部消す。
/(\d{3})(\d{4})(\d{4})/ で「3桁・4桁・4桁」に分けて $1-$2-$3 で再構成する。

この「キャプチャして、置換側で $1 $2 として使う」のが、正規表現置換の強力なところです。


置換側で「マッチした内容」を使うテクニック

キャプチャグループと , , …

さっきの電話番号の例のように、
正規表現の中で () で囲んだ部分は「キャプチャグループ」として、
置換文字列の中で $1, $2, … として参照できます。

"2026-02-19".replace(/(\d{4})-(\d{2})-(\d{2})/, "$1/$2/$3");
// "2026/02/19"
JavaScript

(\d{4})$1
(\d{2})$2
(\d{2})$3

という対応です。

関数を渡して、もっと柔軟に置換する

置換側に「文字列」ではなく「関数」を渡すこともできます。

const text = "price: 1200, tax: 120";

const result = text.replace(/\d+/g, (match) => {
  const num = Number(match);
  return (num * 2).toString();
});

console.log(result); // "price: 2400, tax: 240"
JavaScript

ここでは、

\d+ で数字のまとまりにマッチする。
マッチしたたびにコールバック関数が呼ばれる。
match にはマッチした文字列(”1200″ や “120”)が入る。
それを数値に変換して2倍して、文字列に戻して返す。

という流れです。

業務でいうと、

金額を一括で税抜→税込に変換する。
特定のパターンだけマスクする。
ログの中の ID を別の形式に変換する。

といった処理を、かなり柔軟に書けます。


正規表現置換ユーティリティをどう設計するか

「よく使うパターン」を関数に切り出す

正規表現そのものは強力ですが、
毎回 /\s+/g/\D+/g を生で書いていると、
読みづらいし、コピペミスもしやすくなります。

なので、業務でよく使うものは、
「意味のある名前を付けたユーティリティ」にしてしまうのがおすすめです。

例えば:

export function collapseSpaces(text) {
  return replaceAllRegex(text, /\s+/g, " ");
}

export function removeNonDigits(text) {
  return replaceAllRegex(text, /\D+/g, "");
}
JavaScript

呼び出し側は、

collapseSpaces("a   b    c");   // "a b c"
removeNonDigits("TEL: 03-1234-5678"); // "0312345678"
JavaScript

のように、「何をしたいか」だけを読めば意味が分かるコードになります。

「生の正規表現」を散らさない

プロジェクトのあちこちに /\s+/g/\d{4}-\d{2}-\d{2}/ が散らばると、
仕様変更(例えば「日付のフォーマットが変わった」)のときに地獄を見ます。

なので、

正規表現はできるだけユーティリティ関数の中に閉じ込める。
呼び出し側は「意味のある関数名」だけを見る。

という構造にしておくと、
後から見たときの理解コストも、変更コストも一気に下がります。


ちょっとだけ手を動かしてみる

コンソールで、次のあたりを試してみてください。

"abc123def456".replace(/\d+/g, "");
"a   b    c".replace(/\s+/g, " ");
"2026-02-19".replace(/(\d{4})-(\d{2})-(\d{2})/, "$1/$2/$3");

replaceAllRegex("abc123def456", /\d+/g, "");
replaceAllRegex("a   b    c", /\s+/g, " ");
JavaScript

「どこがマッチして、どう置き換わるか」を目で確認すると、
正規表現置換のイメージがかなりクリアになります。

そのうえで、自分のプロジェクトに

export function replaceAllRegex(text, pattern, replacement) { ... }
export function collapseSpaces(text) { ... }
export function removeNonDigits(text) { ... }
JavaScript

のようなユーティリティを一つ置いて、
「パターンで置き換えたいときは必ずここを通す」
というルールにしてみてください。

それができた瞬間、あなたの文字列処理は
「場当たり的な replace の寄せ集め」から
「意図を持って設計された正規表現置換ユーティリティ」に、一段レベルアップします。

タイトルとURLをコピーしました