preg_match_all 是 PHP 中執行全域正則表達式匹配的核心函數。它會在目標字符串中搜尋所有符合模式的內容,並按指定順序將結果存入數組。與 preg_match 只匹配第一次不同,它能一次性獲取所有匹配項。
int preg_match_all ( string $pattern, string $subject, array &$matches [, int $flags = PREG_PATTERN_ORDER [, int $offset = 0 ]] )
/.../ 或 |...|)。PREG_PATTERN_ORDER(默認)與 PREG_SET_ORDER。返回整個模式匹配的次數(可能為零),出錯返回 FALSE。
結果按「模式分組」排序:
$matches[0]:完整模式匹配的所有字符串組成的數組。$matches[1]:第一個捕獲組匹配的所有字符串組成的數組。$matches[2]:第二個捕獲組... 以此類推。示例:
<?php
$subject = "<b>example: </b><div align=left>this is a test</div>";
preg_match_all("|<[^>]+>(.*)</[^>]+>|U", $subject, $out, PREG_PATTERN_ORDER);
print_r($out[0]); // 完整標簽匹配
// Array ( [0] => <b>example: </b> [1] => <div align=left>this is a test</div> )
print_r($out[1]); // 第一個捕獲組(標簽內容)
// Array ( [0] => example: [1] => this is a test )
結果按「匹配項分組」排序:
$matches[0]:第一組匹配的所有內容(完整匹配、捕獲組1、捕獲組2...)。$matches[1]:第二組匹配的所有內容...示例:
<?php
preg_match_all("|<[^>]+>(.*)</[^>]+>|U", $subject, $out, PREG_SET_ORDER);
print_r($out[0]);
// Array ( [0] => <b>example: </b> [1] => example: )
print_r($out[1]);
// Array ( [0] => <div align=left>this is a test</div> [1] => this is a test )
若設置此標記,返回數組的每個單元將變為 [matched_string, offset] 形式,即同時返回匹配字符串及其在 subject 中的偏移量。PHP 4.3.0+ 可用。
<?php
$text = "Call 555-1212 or 1-800-555-1212";
preg_match_all("/\(?(\d{3})?\)?[-.\s]?\d{3}[-.\s]\d{4}/x", $text, $phones);
print_r($phones[0]);
<?php
$html = "<b>bold text</b><a href=howdy.html>click me</a>";
// 使用反向引用 \2 匹配同名閉合標簽
preg_match_all("/(<(\w+)[^>]*>)(.*)(<\/\\2>)/", $html, $matches);
for ($i = 0; $i < count($matches[0]); $i++) {
echo "matched: " . $matches[0][$i] . "\n";
echo "part 1 (open tag): " . $matches[1][$i] . "\n";
echo "part 2 (tag name): " . $matches[2][$i] . "\n";
echo "part 3 (content): " . $matches[3][$i] . "\n";
echo "part 4 (close tag): " . $matches[4][$i] . "\n\n";
}
輸出:
matched: <b>bold text</b>
part 1: <b>
part 2: bold text
part 3: </b>
matched: <a href=howdy.html>click me</a>
part 1: <a href=howdy.html>
part 2: click me
part 3: </a>
.* 會匹配盡可能多字符,導致跨標簽匹配。使用 U 修飾符(非貪婪)或 .*? 解決。\\2 代表反向引用)。offset 參數避免記憶體耗盡。preg_match_all 是文本解析、數據提取的利器。掌握 PREG_PATTERN_ORDER 與 PREG_SET_ORDER 的區別,能讓你根據業務需求靈活選擇數據結構,編寫更清晰的解析邏輯。