【PHP8.x】RegexIterator::ALL_MATCHES定数の使い方
ALL_MATCHES定数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
『ALL_MATCHES定数は、RegexIteratorクラスの動作モードを指定するための定数です。この定数をRegexIteratorのコンストラクタの第3引数に設定すると、イテレータが処理する各要素に対して正規表現検索を行い、一致したすべての部分を配列として返します。これは、PHPの標準関数であるpreg_match_all()と同様の動作となり、マッチした結果が多次元配列の形式で得られます。例えば、一つの文章の中から複数のURLやメールアドレスをすべて抽出したい場合にこのモードは非常に役立ちます。デフォルトの動作では正規表現にマッチした要素全体が返されますが、ALL_MATCHESモードを使用することで、要素の中からパターンに一致した箇所だけを正確に、そして一度にすべて取得することが可能になります。これにより、複雑な文字列データから必要な情報を効率的に抜き出す処理を簡潔に記述できます。』
構文(syntax)
1<?php 2 3$lines = new ArrayIterator([ 4 'Error on line 10, Warning on line 25', 5 'Notice on line 30', 6 'No issues here', 7 'Fatal error on line 45' 8]); 9 10$iterator = new RegexIterator( 11 $lines, 12 '/(\w+) on line (\d+)/', 13 RegexIterator::ALL_MATCHES 14); 15 16foreach ($iterator as $lineKey => $matches) { 17 echo "Matches found in original line {$lineKey}:" . PHP_EOL; 18 // $matches[0] は全体にマッチした文字列の配列 19 // $matches[1] は1番目のキャプチャグループの配列 (Error, Warningなど) 20 // $matches[2] は2番目のキャプチャグループの配列 (10, 25など) 21 print_r($matches); 22} 23 24?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
戻り値なし
戻り値はありません
サンプルコード
PHP RegexIterator::ALL_MATCHES で全マッチ取得
1<?php 2 3/** 4 * RegexIterator::ALL_MATCHES 定数の動作をデモンストレーションします。 5 * 6 * この定数は、RegexIterator::GET_MATCH モードと組み合わせることで、 7 * 各要素(文字列)内の最初のマッチだけでなく、すべてのマッチを抽出するように 8 * RegexIterator に指示します。 9 * 10 * @return void 11 */ 12function demonstrateRegexIteratorAllMatches(): void 13{ 14 // 処理対象となる文字列の配列 15 $data = [ 16 "apple_123_banana_456", 17 "orange_789", 18 "no_numbers_here", 19 "multiple_digits_0_1_2_3", 20 ]; 21 22 // 配列からイテレータを作成し、RegexIterator の基盤とします 23 $arrayIterator = new ArrayIterator($data); 24 25 // 数字の並びを検索するための正規表現パターン 26 $pattern = '/\d+/'; 27 28 echo "--- RegexIterator::GET_MATCH モード (ALL_MATCHES なし) ---\n"; 29 echo "各要素内で最初に見つかったマッチのみを抽出します。\n"; 30 31 // RegexIterator::GET_MATCH モードで、ALL_MATCHES フラグなしで初期化 32 // これにより、各文字列で最初に見つかった数字のみが抽出されます。 33 $firstMatchIterator = new RegexIterator( 34 $arrayIterator, 35 $pattern, 36 RegexIterator::GET_MATCH 37 ); 38 39 foreach ($firstMatchIterator as $key => $matchResult) { 40 // $matchResult は preg_match の結果と同様の配列です (例: ['123']) 41 // 見つからない場合は $matchResult が空になるので 'N/A' を表示 42 echo "元の文字列: '{$data[$key]}', 最初のマッチ: " . ($matchResult[0] ?? 'N/A') . "\n"; 43 } 44 echo "\n"; 45 46 // 基盤となるイテレータをリセットし、再度最初から処理できるようにします 47 $arrayIterator->rewind(); 48 49 echo "--- RegexIterator::GET_MATCH モード (ALL_MATCHES あり) ---\n"; 50 echo "各要素内で見つかったすべてのマッチを抽出します。\n"; 51 52 // RegexIterator::GET_MATCH モードで、RegexIterator::ALL_MATCHES フラグを付けて初期化 53 // これにより、各文字列で見つかったすべての数字が抽出されます。 54 $allMatchesIterator = new RegexIterator( 55 $arrayIterator, 56 $pattern, 57 RegexIterator::GET_MATCH, 58 RegexIterator::ALL_MATCHES // このフラグがすべてのマッチを抽出するよう動作を変更します 59 ); 60 61 foreach ($allMatchesIterator as $key => $allMatchResults) { 62 // $allMatchResults は、各マッチの配列の配列になります (例: [['123'], ['456']]) 63 // 各マッチの実際の値 (例: '123') を取り出して表示します 64 $extractedMatches = array_map(fn($m) => $m[0], $allMatchResults); 65 echo "元の文字列: '{$data[$key]}', すべてのマッチ: " . implode(', ', $extractedMatches) . "\n"; 66 } 67} 68 69// デモンストレーション関数を実行 70demonstrateRegexIteratorAllMatches();
PHP 8のRegexIteratorクラスに定義されているALL_MATCHESは、正規表現による検索動作を制御するための定数です。この定数自体に引数はなく、特定の値を返すこともありませんが、RegexIteratorの動作モード、特にRegexIterator::GET_MATCHモードと組み合わせて使用することで、その挙動に影響を与えます。
通常、RegexIterator::GET_MATCHモードで正規表現検索を行うと、各要素内で最初に見つかったパターンに合致する部分のみが抽出されます。しかし、ALL_MATCHES定数を追加して使用すると、RegexIteratorは各要素内で見つかる正規表現パターンに合致する「すべて」の部分を抽出するようになります。
提供されたサンプルコードでは、"apple_123_banana_456"のような文字列から数字の並び(/\d+/)を検索しています。ALL_MATCHESなしの場合、"123"のみが抽出されます。一方、ALL_MATCHESを使用した場合、"123"と"456"のように、文字列内のすべての数字の並びが抽出され、配列として返される動作を確認できます。これにより、一つの文字列から複数の情報を一括で取り出したい場合に非常に役立ちます。
RegexIterator::ALL_MATCHESは、RegexIterator::GET_MATCHモードと組み合わせて使用することで、正規表現に一致するすべての部分を抽出するよう動作を切り替えるフラグです。このフラグを付与するかどうかで、イテレータから得られる結果のデータ構造が大きく変わる点に注意が必要です。ALL_MATCHESがない場合は、各要素から最初に見つかったマッチのみが配列として返されますが、ALL_MATCHESを付与すると、各要素で見つかったすべてのマッチが、さらにネストされた配列の配列として返されます。そのため、取得したデータを処理する際は、どちらのモードで取得したかに応じて、適切な方法(例:array_mapなど)で値を取り出す必要があります。この定数は、文字列からのパターン抽出に関する機能であり、文字列の置換を行うものではありません。
PHP RegexIterator ALL_MATCHES で全マッチを取得する
1<?php 2 3// データソースとなる文字列の配列を準備します。 4$data = [ 5 'Item 1: Price is $10.50.', 6 'Item 2: Quantity 20, Cost $5.00 each.', 7 'Item 3: Total 123 items.', 8 'No numbers here.', // この行は正規表現にマッチしないため、後でスキップされます 9 'Item 4: Discounts 5% and 10%.', 10]; 11 12// ArrayIterator を使用して、PHPの配列をイテレータ(反復処理可能なオブジェクト)に変換します。 13// これにより、RegexIterator で処理できるようになります。 14$arrayIterator = new ArrayIterator($data); 15 16// 検索したい正規表現パターンを定義します。 17// この例では、1つ以上の連続した数字(例: "10", "20", "123")にマッチします。 18$pattern = '/\d+/'; 19 20// RegexIterator をインスタンス化します。 21// RegexIterator は、基となるイテレータの要素を正規表現でフィルタリングし、 22// さらにそのマッチ結果を特定の形式で返すことができるイテレータです。 23// 24// 第一引数: 処理対象となるイテレータ ($arrayIterator)。 25// 第二引数: 適用する正規表現パターン ($pattern)。 26// 第三引数: モード。RegexIterator::ALL_MATCHES を指定すると、 27// 各イテレータ要素内で正規表現にマッチするすべての部分文字列が結果として返されます。 28// このモードでは、マッチした各部分文字列がそれぞれ配列として格納されます(例: [['10'], ['50']])。 29$regexIterator = new RegexIterator( 30 $arrayIterator, 31 $pattern, 32 RegexIterator::ALL_MATCHES 33); 34 35echo "指定されたデータから正規表現 '{$pattern}' にマッチするすべての数字のまとまりを検索します。\n"; 36echo "RegexIterator::ALL_MATCHES モードを使用しています。\n\n"; 37 38// RegexIterator をループし、マッチした結果を表示します。 39// RegexIterator は正規表現にマッチする要素のみを返します。 40// $key は元の配列のインデックス、 $matches は現在の要素で見つかったすべてのマッチの配列です。 41foreach ($regexIterator as $key => $matches) { 42 echo "元のデータ: '" . $data[$key] . "'\n"; 43 44 $matchedValues = []; 45 foreach ($matches as $match) { 46 // 各 $match は配列であり、その最初の要素 ([0]) が正規表現にマッチした文字列全体です。 47 $matchedValues[] = $match[0]; 48 } 49 echo "マッチした値: " . implode(', ', $matchedValues) . "\n"; 50 echo "--------------------\n"; 51} 52 53?>
RegexIterator::ALL_MATCHES定数は、PHPのRegexIteratorクラスで使用され、正規表現のマッチング動作を制御するモードの一つです。この定数をRegexIteratorのコンストラクタの第三引数として指定すると、基となるデータから正規表現にマッチするすべての部分文字列を抽出するようRegexIteratorに指示します。
サンプルコードでは、まずArrayIteratorを使って文字列の配列を反復可能なオブジェクトに変換し、これをRegexIteratorの処理対象としています。定義された正規表現パターン/\d+/は、連続する一つ以上の数字にマッチします。
RegexIteratorのインスタンス化時にRegexIterator::ALL_MATCHESモードを設定すると、各元のデータ要素に対し、パターンに合致するすべての数字のまとまりが個別に抽出されます。例えば、"Item 1: Price is $10.50."という文字列からは、"10"と"50"の両方が見つけ出されます。
このモードでは、RegexIteratorはループごとに、マッチした部分文字列の配列(サンプルコードの$matches変数)を返します。この配列の内部では、マッチした各部分文字列がそれぞれ別の配列(例: ['10']、['50'])として格納されているため、$match[0]のようにアクセスして実際のマッチ文字列を取り出すことができます。これにより、一つの文字列内に複数のマッチが存在する場合でも、それらすべてを漏らさず取得し、処理することが可能になります。
RegexIterator::ALL_MATCHES モードは、各データ要素内で正規表現に合致する全ての部分文字列を抽出する際に利用します。正規表現にマッチしないデータ要素は結果から除外されます。foreach ループで得られる $matches は多次元配列で返され、$match[0] でマッチした文字列全体にアクセスします。正規表現パターン $pattern の記述が重要です。意図通りの動作か、十分なテストで確認してください。RegexIterator は ArrayIterator 以外にも様々なイテレータと連携可能です。