フロントエンドの第一線で戦っている諸君、お疲れ様。
今日は、正規表現とJavaScriptの「深淵」に少しだけ足を踏み入れようと思う。
多くの開発者が、文字列のパースに `match()` や `replace()` を使って苦労している場面をよく見かける。「正規表現が読みにくい」「インデックスの管理が面倒でバグの温床になる」……そう嘆くのは、まだ道具を使いこなせていない証拠だ。
今日は、モダンJavaScriptの隠し武器である 「名前付きキャプチャグループ」と `matchAll()` を使った、保守性の高いデータ抽出術を伝授する。
—
なぜ、ただの `match()` ではダメなのか?
古くからある `match()` にフラグ `g` をつけて実行すると、マッチした文字列の配列は返してくれるが、肝心の「グループ情報」が抜け落ちることが多い。配列のインデックス `[1]` や `[2]` を見て、「これは何番目のグループだっけ?」と正規表現とソースコードを往復する……そんな泥臭い開発とは今日でお別れだ。
名前付きキャプチャグループ `(?…)`
正規表現の中に `(?
実践:複雑なログやデータ構造をスマートに処理する
例えば、サーバーから返ってくる「`YYYY-MM-DD:LEVEL:MESSAGE`」という形式のログをパースする場合を考える。
const logData = `
2023-10-27:INFO:User login
2023-10-27:WARN:Slow response
2023-10-28:ERROR:Database connection failed
`;
// 名前付きキャプチャグループを使って定義する
// /g フラグを忘れずに。matchAllはイテレータを返すための必須条件だ
const regex = /(?
// matchAllでイテレータを取得
const matches = logData.matchAll(regex);
for (const match of matches) {
// ここが重要:groupsプロパティにアクセスするだけで、
// 正規表現で定義した名前がそのままキーとして取得できる
const { date, level, message } = match.groups;
console.log(`[${level}] ${date} に発生: ${message}`);
}
どうだろう。`match[1]` のようなマジックナンバーを使う必要は一切ない。コードの可読性が段違いだ。
—
ブラウザの裏側で起きていること:イテレータの旨味
なぜわざわざ `matchAll` なのか? それは、「メモリ効率」と「制御の柔軟性」のためだ。
`match()` はマッチした全要素をメモリ上に配列として展開する。もし対象の文字列が数万行あるような巨大なログだったらどうなるか? メモリを圧迫し、UIスレッドをブロックするリスクがある。
一方、`matchAll()` が返すのは「正規表現のイテレータ」だ。
これは、ループを回すたびに「次のマッチ箇所」を走査する。つまり、巨大なデータであっても、必要な分だけを順次処理できるため、ブラウザのパフォーマンスを損なわない。これは、大規模なデータグリッドやログビューアを実装する際、シニアとして意識すべき「プロの作法」だ。
—
実務で差がつく!「結果をそのままオブジェクト配列に変換」
現場では、抽出したデータをそのまま `Array` にして扱いたいケースがほとんどだ。スプレッド構文を組み合わせれば、一行で変換できる。
const text = “ID:101, NAME:Alice; ID:102, NAME:Bob;”;
const pattern = /ID:(?
// Array.fromでイテレータを配列に変換し、groupsだけを抽出する
const users = Array.from(text.matchAll(pattern), m => m.groups);
/
出力結果:
[
{ id: “101”, name: “Alice” },
{ id: “102”, name: “Bob” }
]
/
console.log(users);
この書き方を知っているだけで、APIのレスポンスパースやフォームのバリデーションロジックは劇的に短く、かつ堅牢になる。
—
シニアからのアドバイス
正規表現は強力だが、「複雑にしすぎない」のが鉄則だ。
- `(?
…)` を多用して複雑なパースを一行でやろうとすると、後から読んだときに後悔する。 - もし正規表現が2行以上になるなら、それはもう「小さなパーサーを書くべき時」かもしれない。
だが、今回紹介した「名前付きキャプチャグループ」を活用すれば、コードの意図(どの部分を何として扱いたいか)が明確になり、正規表現の「黒魔術感」をかなり中和できるはずだ。
明日からの開発で、ぜひ `matchAll` と `groups` を使ってみてくれ。あなたの書くコードが、少しでも「美しく、力強いもの」になることを期待している。
何か詰まったら、いつでも聞いてくれ。現場からは以上だ。

コメント