【PHP8.x】RecursiveRegexIterator::MATCH定数の使い方
MATCH定数の使い方について、初心者にもわかりやすく解説します。
基本的な使い方
MATCH定数は、RecursiveRegexIteratorクラスの動作モードを指定するための定数です。RecursiveRegexIteratorは、ディレクトリ構造のように階層を持つデータ群を再帰的に処理しながら、指定した正規表現に一致する要素だけを抽出するためのクラスです。このクラスを利用する際、どのよう な基準で要素を返すかをコンストラクタの引数で設定する必要があり、その設定値の一つがこのMATCH定数です。具体的には、動作モードとしてRecursiveRegexIterator::MATCHを指定すると、イテレータが処理する現在の要素が正規表現パターンにマッチした場合にのみ、その要素そのものを結果として返します。これは、正規表現をフィルターとして用い、条件に一致したデータだけを選択するという、最も基本的なフィルタリング処理を指示するモードです。このMATCH定数はデフォルトの動作モードでもあるため、もしモード指定を省略してRecursiveRegexIteratorのインスタンスを生成した場合は、このモードが自動的に適用されます。
構文(syntax)
1<?php 2 3$filePaths = [ 4 'image.jpg', 5 'document.pdf', 6 'archive.zip', 7 'photo.jpg', 8 'script.php', 9 'data' => [ 10 'backup.zip', 11 'log.txt', 12 'old_photo.jpg' 13 ] 14]; 15 16$arrayIterator = new RecursiveArrayIterator($filePaths); 17 18$regexIterator = new RecursiveRegexIterator( 19 $arrayIterator, 20 '/\.(jpg|zip)$/', 21 RecursiveRegexIterator::MATCH 22); 23 24$iterator = new RecursiveIteratorIterator($regexIterator); 25 26foreach ($iterator as $path) { 27 echo $path . PHP_EOL; 28} 29 30?>
引数(parameters)
引数なし
引数はありません
戻り値(return)
int
RecursiveRegexIterator::MATCH は、正規表現にマッチした要素を返すための定数です。
サンプルコード
PHP: RecursiveRegexIterator::MATCH で正規表現マッチする
1<?php 2 3/** 4 * RecursiveRegexIterator::MATCH を使用した再帰的な正規表現フィルタリングの例 5 * 6 * この関数は、指定された多次元配列に対して正規表現フィルタリングを行い、 7 * マッチした要素のみを返します。 8 * RecursiveRegexIterator::MATCH は、イテレータが正規表現にマッチした要素全体(キーと値)を返すことを示します。 9 * これはデフォルトのモードであり、正規表現マッチの結果自体を返す RecursiveRegexIterator::GET_MATCH と対比されます。 10 * RecursiveIteratorIterator と組み合わせることで、多次元構造を探索し、マッチしたリーフノードを抽出します。 11 * 12 * @param array $data フィルタリングする多次元データ配列 13 * @param string $pattern 使用する正規表現パターン 14 * @return array マッチした要素を含む、キーと値のペアの配列 15 */ 16function filterRecursiveArrayWithRegexMatch(array $data, string $pattern): array 17{ 18 // 多次元配列を再帰的なイテレータに変換します。 19 $arrayIterator = new RecursiveArrayIterator($data); 20 21 // RecursiveRegexIterator を使用して正規表現で要素をフィルタリングします。 22 // RecursiveRegexIterator::MATCH を指定することで、正規表現にマッチした元の要素(キーと値)が返されます。 23 // デフォルトでは、値に対して正規表現が適用されます。 24 $regexIterator = new RecursiveRegexIterator( 25 $arrayIterator, 26 $pattern, 27 RecursiveRegexIterator::MATCH // マッチした元の要素全体(キーと値)を返すモード 28 ); 29 30 // RecursiveIteratorIterator を使用して、RecursiveRegexIterator を再帰的に走査します。 31 // これにより、多次元配列のすべてのリーフノードにアクセスできるようになります。 32 $iterator = new RecursiveIteratorIterator($regexIterator); 33 34 $filteredResults = []; 35 foreach ($iterator as $key => $value) { 36 // RecursiveRegexIterator::MATCH モードにより、 37 // 正規表現にマッチしたリーフノードの元のキーと値を取得できます。 38 $filteredResults[$key] = $value; 39 } 40 41 return $filteredResults; 42} 43 44// サンプルデータの準備(多次元配列) 45$data = [ 46 'fruits' => [ 47 'apple', 48 'banana', 49 'grape', 50 'melon', 51 ], 52 'vegetables' => [ 53 'root_vegetable' => 'carrot', 54 'leaf_vegetable' => 'broccoli', 55 ], 56 'proteins' => [ 57 'meat' => 'chicken', 58 'fish' => 'salmon', 59 ], 60 'nuts_and_seeds' => [ 61 'almond', 62 'walnut', 63 'peanut', 64 ], 65 'dairy' => 'milk', 66 'grains' => 'rice', 67]; 68 69// 正規表現パターン1: 'a' を含む文字列を検索 (大文字・小文字を区別しない) 70$pattern1 = '/a/i'; 71 72echo "=== Original Data ===\n"; 73print_r($data); 74echo "\n"; 75 76echo "=== Filtering with pattern: '{$pattern1}' (contains 'a' or 'A') ===\n"; 77$filteredData1 = filterRecursiveArrayWithRegexMatch($data, $pattern1); 78print_r($filteredData1); 79echo "\n"; 80 81// 正規表現パターン2: 'e' で終わる文字列を検索 (大文字・小文字を区別しない) 82$pattern2 = '/e$/i'; 83echo "=== Filtering with pattern: '{$pattern2}' (ends with 'e' or 'E') ===\n"; 84$filteredData2 = filterRecursiveArrayWithRegexMatch($data, $pattern2); 85print_r($filteredData2); 86
PHPのRecursiveRegexIterator::MATCHは、RecursiveRegexIteratorクラスが正規表現にマッチした要素をどのように返すかを定義する整数型の定数です。この定数は、イテレータが正規表現パターンに合致する要素を見つけた際に、その要素のキーと値のペア全体を返すように指示します。
サンプルコードのfilterRecursiveArrayWithRegexMatch関数では、多次元配列を再帰的に探索し、正規表現でフィルタリングする目的でこの定数を使用しています。RecursiveArrayIteratorとRecursiveIteratorIteratorと組み合わせてRecursiveRegexIteratorを使うことで、多次元構造の奥深くにある要素にも正規表現を適用できます。RecursiveRegexIterator::MATCHが指定されているため、正規表現にマッチした要素は、その元のキーと値がそのままの形で抽出され、新しい配列に格納されます。これは、マッチした部分文字列自体を返すRecursiveRegexIterator::GET_MATCHとは異なり、フィルタリングによって元のデータ構造の一部を抽出したい場合に非常に有用です。
このサンプルコードでは、多次元配列から正規表現にマッチする要素を抽出する際に、RecursiveRegexIterator::MATCH定数を使用しています。この定数は、正規表現にマッチした元のデータ要素(キーと値のペア)をそのまま返すモードであることを理解してください。デフォルトでは配列の値に対して正規表現が適用されますが、キーを対象にしたい場合は別途設定が必要です。
また、正規表現パターン(例:/a/i)の記述ミスは、意図しないフィルタリング結果を招くため、パターンが正しいか注意深く確認することが重要です。MATCHモードは、マッチした要素自体が必要な場合に適しており、正規表現のマッチ結果(例:キャプチャグループ)が必要な場合はRecursiveRegexIterator::GET_MATCHを使用するなど、用途に応じたモード選択が大切です。複数のイテレータを組み合わせて再帰的な処理を行っているため、それぞれの役割を把握すると、より安全で正確なコード利用につながります。
PHP: 複数行データから正規表現で抽出する
1<?php 2 3/** 4 * 複数行のテキストデータから、正規表現にマッチする特定の情報を抽出する例。 5 * RecursiveRegexIterator::MATCH 定数を使用して、マッチしたキャプチャグループのみを取得します。 6 */ 7function processMultiLineDataWithRegexIterator(): void 8{ 9 // 処理対象の複数行データ。各配列要素が1行と見なされます。 10 // このデータの中から、特定の形式を持つ行(ID、Name、Statusを含む行)を抽出します。 11 $textData = [ 12 "ID: 001, Name: Alice, Status: Active", 13 "ID: 002, Name: Bob, Status: Inactive", 14 "Invalid line data", // この行はパターンにマッチしないため、フィルタリングされて表示されません。 15 "ID: 003, Name: Charlie, Status: Active", 16 "Additional info: Eve", // この行もフィルタリングされて表示されません。 17 ]; 18 19 // ArrayIterator を使用して、PHPの配列をイテレータとして扱います。 20 // RecursiveRegexIterator はイテレータを処理するため、このようなラップが必要です。 21 $arrayIterator = new ArrayIterator($textData); 22 23 // RecursiveRegexIterator を初期化します。 24 // これは、正規表現によってイテレータの要素をフィルタリングするためのものです。 25 // - 第一引数 ($arrayIterator): フィルタリング対象のベースとなるイテレータ。 26 // - 第二引数 ('/^ID: (\d+), Name: ([a-zA-Z]+), Status: (Active|Inactive)$/m'): 正規表現パターン。 27 // - `^` と `$` は行の先頭と末尾にマッチします(`m` 修飾子により、各配列要素=各行に適用されます)。 28 // - `(\d+)`: 数字のグループ (ID) をキャプチャします。これが最初のキャプチャグループになります。 29 // - `([a-zA-Z]+)`: アルファベットのグループ (Name) をキャプチャします。これが2番目のキャプチャグループです。 30 // - `(Active|Inactive)`: "Active" または "Inactive" のいずれかをキャプチャします (Status)。これが3番目のキャプチャグループです。 31 // - `m` 修飾子: マルチラインモード(複数行モード)。`^` と `$` が各行の開始/終了にマッチするようになります。 32 // - 第三引数 (RecursiveRegexIterator::MATCH): マッチングモード。 33 // - `RecursiveRegexIterator::MATCH` は、正規表現のキャプチャグループ(括弧で囲まれた部分)と全体マッチを配列として返します。 34 $regexIterator = new RecursiveRegexIterator( 35 $arrayIterator, 36 '/^ID: (\d+), Name: ([a-zA-Z]+), Status: (Active|Inactive)$/m', 37 RecursiveRegexIterator::MATCH 38 ); 39 40 echo "--- マッチしたデータ (ID, Name, Status) ---\n"; 41 echo "ID | Name | Status\n"; 42 echo "--------------------------\n"; 43 44 // イテレータをループして、マッチした結果を表示します。 45 // RecursiveRegexIterator::MATCH モードでは、$matches 変数には、 46 // マッチした全体($matches[0])と、各キャプチャグループの結果($matches[1]、$matches[2]、$matches[3]...)が配列として格納されます。 47 foreach ($regexIterator as $originalLineIndex => $matches) { 48 // sprintf を使用して、整形された出力を生成します。 49 echo sprintf( 50 "%s | %-7s | %s\n", 51 $matches[1], // ID (最初のキャプチャグループ) 52 $matches[2], // Name (2番目のキャプチャグループ) 53 $matches[3] // Status (3番目のキャプチャグループ) 54 ); 55 } 56 echo "--------------------------\n"; 57} 58 59// 定義した関数を実行します。 60processMultiLineDataWithRegexIterator();
PHP 8のRecursiveRegexIterator::MATCH定数は、正規表現を使ってイテレータの各要素をフィルタリングする際に、正規表現にマッチしたキャプチャグループ(正規表現の括弧で囲まれた部分)と全体のマッチ結果を配列として取得するためのモードを指定します。この定数自体には引数はなく、内部的に整数値が返されます。
サンプルコードでは、複数行のテキストデータから、ID、Name、Statusといった特定の形式を持つ情報を正規表現で抽出し、その詳細を表示する例を示しています。まず、処理対象の配列をArrayIteratorでラップし、これをRecursiveRegexIteratorの第一引数に渡します。第二引数には、抽出したいデータのパターンを定義した正規表現を指定し、m修飾子によって各配列要素(行)が独立した文字列として扱われるようにします。第三引数にRecursiveRegexIterator::MATCH定数を指定することで、正規表現にマッチしたキャプチャグループを個別に取得できるようになります。
ループ処理では、$matches変数に、マッチした全体の文字列($matches[0])と、正規表現で定義された各キャプチャグループ(例: ID、Name、Status)の結果が配列の要素($matches[1], $matches[2], $matches[3]など)として格納されます。これにより、正規表現に合致するデータのみを効率的に抽出し、必要な情報だけを整形して表示することが可能になります。例えば、パターンに合致しない行は自動的にフィルタリングされ、結果には表示されません。
このコードでは、RecursiveRegexIterator::MATCH定数を用いることで、正規表現にマッチした全体文字列に加え、括弧で囲まれたキャプチャグループが配列要素として取得されます。foreachループ内では、$matches[0]が全体マッチ、$matches[1]以降が各キャプチャグループの結果となりますので、正しいインデックスを指定してアクセスすることが重要です。正規表現のm修飾子は、複数行モードを有効にし、^と$が行の開始と終わりにマッチするために不可欠です。この修飾子の有無で正規表現の挙動が大きく変わるため、注意して設定してください。イテレータを組み合わせることで、大量のデータをメモリ効率良く処理できる利点がありますが、正規表現が複雑すぎると処理速度に影響が出る可能性があります。また、正規表現にマッチしない行は自動的にスキップされるため、意図したデータがすべて抽出されるか、正規表現パターンを慎重に確認することが大切です。