---
type: reference
language: javascript
slug: regexp/test-match
title: "正規表現で探す — test() と match() と matchAll()"
title_tag: "JavaScript 正規表現の使い方 — test と match の違い"
summary: >
  あるかどうかだけなら test()、取り出すなら match()、全部取り出すなら matchAll() です。
  g フラグを付けたときに戻り値の形が変わること、test() が前回の位置を覚えてしまう罠まで確かめます。
description: >
  同じ g フラグでも test() は前回の位置を覚え、match() は戻り値の形が変わります。
  使い分けの基準、名前付きグループ、特殊文字の打ち消しまで実行して確かめられます。
status: published
difficulty: 3
minutes: 10

versions:
  verified: "Node 22.22.3"
  since: "ES3"
  deprecated: null
  removed: null

sources:
  - title: "RegExp (Regular Expression) Objects — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-regexp-regular-expression-objects"
  - title: "String.prototype.matchAll — ECMAScript® 2026 Language Specification"
    url: "https://tc39.es/ecma262/#sec-string.prototype.matchall"
  - title: "正規表現 — MDN"
    url: "https://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Regular_expressions"

terms: [正規表現, グローバルフラグ, キャプチャ, lastIndex]

links:
  related:
    - javascript/reference/string/replace
    - javascript/learn/string/search
    - javascript/reference/string/split

content_updated_at: 2026-09-08
published_at: 2026-09-08
---

**あるかどうかだけ**なら `test()` です。真偽値が返ります。

```js run
const hasDigit = /\d+/;

console.log(hasDigit.test('a12b'));
console.log(hasDigit.test('abc'));
```
```output
true
false
```

**取り出したい**なら `match()` です。

```js run
console.log('a12b'.match(/\d+/));
console.log('abc'.match(/\d+/));
```
```output
[ '12' ]
null
```

見つからないときは[bad:空配列ではなく `null`]です。**そのまま `[0]` を読むと落ちます。**

## 使い分け

| したいこと | 使うもの | 見つからないとき |
|---|---|---|
| あるか無いか | `re.test(s)` | `false` |
| 最初の1つを取り出す | `s.match(re)` | [bad:`null`] |
| 全部取り出す | `[...s.matchAll(re)]` | 空配列 |
| 位置だけ欲しい | `s.search(re)` | [num:-1] |
| 置き換える | `s.replace(re, ...)` | 元のまま |

**`null` が返るのは `match()` だけ**です。ここが事故の起点になります。

```js run
const found = 'abc'.match(/\d+/);

console.log(found?.[0] ?? '見つからない');
```
```output
見つからない
```

## `g` を付けると戻り値の形が変わる

```js run
console.log('a12b34'.match(/\d+/));
console.log('a12b34'.match(/\d+/g));
```
```output
[ '12' ]
[ '12', '34' ]
```

見た目は似ていますが**中身が違います。**

- `g` なし … 最初の1つ。`[0]` が一致した文字列、`[1]` 以降が[type:キャプチャ]
- `g` あり … 一致した文字列だけを並べた配列。**キャプチャは消える**

`g` を付けると「どこで一致したか」も「括弧の中身」も失われます。

## 全部を、中身つきで取り出す

`matchAll()` を使います。

```js run
const found = [...'a1b22c'.matchAll(/(\w)(\d+)/g)];

console.log(found.length);
console.log(found.map((m) => m[0]));
console.log(found.map((m) => [m[1], m[2]]));
console.log(found[0].index);
```
```output
2
[ 'a1', 'b22' ]
[ [ 'a', '1' ], [ 'b', '22' ] ]
0
```

**一致ごとに、キャプチャも位置も持ったまま**取れます。
戻り値は[type:イテレータ]なので、`[...]` で配列にしてから使います。

`g` を忘れると例外になります。

```js bad
try {
  [...'a1'.matchAll(/\d/)];
} catch (error) {
  console.log(error.name);
}
```
```output
TypeError
```

[dim:文言は「String.prototype.matchAll called with a non-global RegExp argument」（Node 22.22.3）。処理系によって変わります。]

## 名前を付けて取り出す

`(?<名前>…)` と書くと、`groups` から引けます。

```js run
const m = '2026-09-08'.match(/(?<y>\d{4})-(?<mo>\d{2})-(?<d>\d{2})/);

console.log(m.groups.y, m.groups.mo, m.groups.d);
console.log(m[0]);
console.log(m.index);
```
```output
2026 09 08
2026-09-08
0
```

**番号で数えるより壊れにくくなります。**
括弧を1つ足しただけで `m[2]` が別のものを指す、という事故が起きません。

## いちばんの落とし穴：`g` 付きの `test()`

```js bad
const re = /a/g;

console.log(re.test('aa'), re.lastIndex);
console.log(re.test('aa'), re.lastIndex);
console.log(re.test('aa'), re.lastIndex);
```
```output
true 1
true 2
false 0
```

**同じ文字列を3回調べたのに、3回目だけ `false` です。**

`g` 付きの正規表現は[key:前回どこまで見たか]を `lastIndex` に覚えています。
`test()` はそこから探し始めるので、**呼ぶたびに結果が変わります。**

`g` を外せば起きません。

```js run
const re = /a/;

console.log(re.test('aa'), re.test('aa'));
```
```output
true true
```

**「あるか無いか」を調べる正規表現に `g` は要りません。**
使い回す正規表現を定数に置いているときほど当たりやすい罠です。

→ [replace() と replaceAll()](/ja/javascript/reference/string/replace/)

## 特殊文字を打ち消す

`.` は「任意の1文字」です。**そのまま書くと別の意味になります。**

```js run
console.log('a.b'.replace(/\./g, '-'));
console.log('a.b'.replace(/./g, '-'));
```
```output
a-b
---
```

文字列から正規表現を作るときは、さらに気をつけてください。

```js run
console.log(new RegExp('a.b').test('axb'));
console.log(new RegExp('a\\.b').test('axb'));
```
```output
true
false
```

`new RegExp()` に渡すのは[key:文字列]なので、`\` を打ち消すのに `\\` が要ります。

> **利用者が入力した文字列を、そのまま正規表現にしないでください。**
> 意図しない一致に加えて、書き方によっては処理が極端に遅くなることがあります。
> 探すだけなら `includes()` で足ります。

[dim:打ち消しを行う `RegExp.escape()` は新しい提案で、Node 22.22.3 にはまだありません。]

## よく使う形

```js run
console.log(/^\d{3}-\d{4}$/.test('123-4567'));
console.log('  a  b  '.replace(/\s+/g, ' ').trim());
console.log('a1b2'.replace(/\d/g, (d) => '[' + d + ']'));
console.log('2026-09-08'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3/$2/$1'));
```
```output
true
a b
a[1]b[2]
08/09/2026
```

- `^` と `$` で[key:全体が一致するか]を見る（付けないと一部でも通る）
- `\s+` で連続した空白をまとめる
- 置き換えに[fn:関数]を渡せる
- `$1` で[type:キャプチャ]を並べ替えられる

## まとめ

- あるか無いかは `test()`、取り出すなら `match()`、全部なら `matchAll()`
- **`match()` は見つからないと `null`。** `?.` で守る
- `g` を付けると `match()` の戻り値から[bad:キャプチャが消える]
- `matchAll()` は `g` が必須。**位置もキャプチャも残る**
- **`g` 付きの `test()` は呼ぶたびに結果が変わる**（`lastIndex`）
- 名前付きグループを使うと、括弧を足しても壊れない
- 文字列から作るときは `\\` で打ち消す。**利用者の入力をそのまま渡さない**

正規表現を使わずに済むなら、そのほうが読みやすくなります。
探すだけ・分けるだけの場面は、こちらにまとめてあります。
→ [文字列を探す・分ける・置き換える](/ja/javascript/learn/string/search/)
