[PHP]preg_match_all関数の使い方を徹底解説!正規表現で複数マッチを取得する方法

PHP

はじめに

PHPで文字列から複数のパターンマッチを取得したいとき、preg_match_all関数は非常に強力なツールです。この記事では、初心者の方にも分かりやすく、preg_match_allの基本から実践的な使い方まで詳しく解説します。

preg_match_allとは?

preg_match_allは、PHPの正規表現関数の一つで、文字列内で正規表現パターンにマッチするすべての箇所を検索し、結果を配列に格納します。

似た関数にpreg_matchがありますが、こちらは最初のマッチのみを返すのに対し、preg_match_allすべてのマッチを取得できる点が大きな違いです。

基本構文

preg_match_all(
    string $pattern,      // 正規表現パターン
    string $subject,      // 検索対象の文字列
    array &$matches = [], // マッチ結果を格納する配列
    int $flags = 0,       // フラグ(オプション)
    int $offset = 0       // 検索開始位置(オプション)
): int|false

戻り値: マッチした回数を返します。マッチしない場合は0、エラーの場合はfalseを返します。

基本的な使用例

例1: すべての数字を抽出

<?php
$text = "私は2024年10月25日に30個のリンゴを買いました。";
$pattern = '/\d+/';  // 1つ以上の数字にマッチ

preg_match_all($pattern, $text, $matches);

print_r($matches);
/*
出力:
Array
(
    [0] => Array
        (
            [0] => 2024
            [1] => 10
            [2] => 25
            [3] => 30
        )
)
*/

echo "数字が" . count($matches[0]) . "個見つかりました。\n";
// 出力: 数字が4個見つかりました。
?>

例2: メールアドレスをすべて抽出

<?php
$text = "連絡先: info@example.com または support@example.jp までご連絡ください。";
$pattern = '/[\w\-\.]+@[\w\-\.]+\.\w+/';

preg_match_all($pattern, $text, $matches);

foreach ($matches[0] as $email) {
    echo "メールアドレス: " . $email . "\n";
}
/*
出力:
メールアドレス: info@example.com
メールアドレス: support@example.jp
*/
?>

フラグの使い方

preg_match_allの第4引数には、結果の格納方法を制御するフラグを指定できます。

PREG_PATTERN_ORDER (デフォルト)

パターンごとに結果をグループ化します。

<?php
$text = "山田太郎は35歳、佐藤花子は28歳です。";
$pattern = '/(\w+)は(\d+)歳/u';

preg_match_all($pattern, $text, $matches, PREG_PATTERN_ORDER);

print_r($matches);
/*
Array
(
    [0] => Array([0] => 山田太郎は35歳, [1] => 佐藤花子は28歳)
    [1] => Array([0] => 山田太郎, [1] => 佐藤花子)
    [2] => Array([0] => 35, [1] => 28)
)
*/
?>

PREG_SET_ORDER

マッチごとに結果をグループ化します。データを扱いやすくなります。

<?php
$text = "山田太郎は35歳、佐藤花子は28歳です。";
$pattern = '/(\w+)は(\d+)歳/u';

preg_match_all($pattern, $text, $matches, PREG_SET_ORDER);

print_r($matches);
/*
Array
(
    [0] => Array([0] => 山田太郎は35歳, [1] => 山田太郎, [2] => 35)
    [1] => Array([0] => 佐藤花子は28歳, [1] => 佐藤花子, [2] => 28)
)
*/

// データの取り出しが簡単
foreach ($matches as $match) {
    echo "{$match[1]}さんは{$match[2]}歳です。\n";
}
?>

PREG_OFFSET_CAPTURE

マッチした文字列の位置(オフセット)も取得します。

<?php
$text = "PHP is great. PHP is powerful.";
$pattern = '/PHP/';

preg_match_all($pattern, $text, $matches, PREG_OFFSET_CAPTURE);

print_r($matches);
/*
Array
(
    [0] => Array
        (
            [0] => Array([0] => PHP, [1] => 0)
            [1] => Array([0] => PHP, [1] => 14)
        )
)
*/
?>

実践的な使用例

HTMLタグから属性を抽出

<?php
$html = '<img src="photo1.jpg" alt="写真1"><img src="photo2.jpg" alt="写真2">';
$pattern = '/<img\s+src="([^"]+)"\s+alt="([^"]+)">/';

preg_match_all($pattern, $html, $matches, PREG_SET_ORDER);

foreach ($matches as $img) {
    echo "画像: {$img[1]}, 説明: {$img[2]}\n";
}
/*
出力:
画像: photo1.jpg, 説明: 写真1
画像: photo2.jpg, 説明: 写真2
*/
?>

URLからパラメータを抽出

<?php
$text = "訪問: https://example.com?id=123&name=test と http://test.com?page=1";
$pattern = '/https?:\/\/[^\s]+/';

preg_match_all($pattern, $text, $matches);

foreach ($matches[0] as $url) {
    echo "URL: " . $url . "\n";
}
?>

CSVのようなデータを解析

<?php
$data = "Tokyo,Japan,13000000\nOsaka,Japan,8800000\nKyoto,Japan,1500000";
$pattern = '/^(\w+),(\w+),(\d+)$/m';  // mフラグで複数行対応

preg_match_all($pattern, $data, $matches, PREG_SET_ORDER);

foreach ($matches as $city) {
    echo "都市: {$city[1]}, 国: {$city[2]}, 人口: {$city[3]}\n";
}
?>

よくある間違いと注意点

1. デリミタを忘れない

正規表現パターンは必ずデリミタ(通常は/)で囲む必要があります。

// ❌ 間違い
$pattern = '\d+';

// ✅ 正しい
$pattern = '/\d+/';

2. UTF-8文字列を扱う場合はu修飾子を使う

日本語などのマルチバイト文字を正しく扱うには、u修飾子が必要です。

$pattern = '/[あ-ん]+/u';  // uを付ける

3. 特殊文字のエスケープ

正規表現の特殊文字(. * + ? [ ] ( ) { } ^ $ | \)を文字として扱いたい場合は、バックスラッシュでエスケープします。

$pattern = '/\$\d+\.\d+/';  // $10.50 のような金額にマッチ

preg_matchとの使い分け

関数用途
preg_match最初の1つだけマッチすればよい場合
preg_match_allすべてのマッチを取得したい場合

例えば、文字列に特定のパターンが含まれているかチェックするだけならpreg_matchすべての該当箇所を取得したいならpreg_match_allを使います。

パフォーマンスの考慮

大量のテキストを処理する場合:

  1. 正規表現をできるだけシンプルに保つ
  2. バックトラック(後戻り)が多くなる複雑なパターンは避ける
  3. 可能であればstrposstr_containsなど単純な文字列関数も検討する

まとめ

preg_match_allは、PHPで複数のパターンマッチを取得する際の必須関数です。

ポイント:

  • すべてのマッチを配列で取得できる
  • フラグで結果の構造を変更可能
  • 正規表現の知識が重要
  • デリミタとエスケープに注意
  • UTF-8ではu修飾子を使用

正規表現は最初は難しく感じるかもしれませんが、慣れると非常に強力なツールになります。ぜひ実際のコードで試してみてください!

参考リンク


この記事が役に立ったら、ぜひシェアしてください!

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