首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

PHP 正則表達式核心函數與元字符完整參考手冊

     編輯:PHP 相關知識

PCRE 正則基礎語法

需要轉義的元字符

$ ^ * ( ) + = { } [ ] | \ / : < > . ? ' "

在模式中使用這些字符作為字面量時,必須前加反斜杠轉義。

Perl 風格定界符與修飾符

模式必須用定界符包圍,常用 /pattern/、#pattern#、~pattern~

修飾符名稱作用
iPCRE_CASELESS不區分大小寫匹配
mPCRE_MULTILINE多行模式:^/$ 匹配每行首尾
sPCRE_DOTALL單行模式:. 匹配換行符
xPCRE_EXTENDED忽略空白和註釋(可讀性)
uPCRE_UTF8UTF-8 模式(處理中文必備)
UPCRE_UNGREEDY非貪婪模式(默認貪婪)
APCRE_ANCHORED強制從字符串開頭匹配
DPCRE_DOLLAR_ENDONLY$ 僅匹配字符串末尾(非行末)
JPCRE_DUPNAMES允許重複命名子組

核心元字符速查表

元字符說明等價/示例
\A字符串開頭(不受 m 影響)^(單行模式)
\z字符串結尾(不受 m 影響)$(單行模式)
\b單詞邊界字母數字與非字母數字交界
\B非單詞邊界\b 反義
\d數字字符[0-9]
\D非數字字符[^0-9]
\s空白字符[ \t\r\n\f\v]
\S非空白字符[^ \t\r\n\f\v]
\w單詞字符[a-zA-Z0-9_]
\W非單詞字符[^a-zA-Z0-9_]
.任意字符(除換行,s 修飾符下含換行).
^行首(m 模式下每行)
$行尾(m 模式下每行)
|分支/或cat|dog
()分組/捕獲(abc)+
(?:)非捕獲分組(?:abc)+
(?P)命名捕獲組(?P\d{4})
[]字符類[a-z], [^0-9]

量詞(貪婪/非貪婪/佔有優先)

貪婪非貪婪佔有優先說明
**?*+0 次或多次
++?++1 次或多次
????+0 次或 1 次
{n}{n}?{n}+恰好 n 次
{n,}{n,}?{n,}+至少 n 次
{n,m}{n,m}?{n,m}+n 到 m 次

佔有優先量詞(PHP 5.2.7+):匹配後不回溯,性能更好,防止災難性回溯。

四大核心函數詳解

1. preg_match - 單次匹配

int preg_match(
    string $pattern,
    string $subject,
    array &$matches = null,
    int $flags = 0,
    int $offset = 0
)
  • 返回:0=不匹配,1=匹配,false=錯誤
  • $matches[0] = 整個模式匹配內容,$matches[1] = 第一個捕獲組...
  • 常用標記:PREG_OFFSET_CAPTURE 返回偏移位置

2. preg_match_all - 全局匹配

int preg_match_all(
    string $pattern,
    string $subject,
    array &$matches = null,
    int $flags = PREG_PATTERN_ORDER
)
  • PREG_PATTERN_ORDER(默認):$matches[0] 全部完整匹配,$matches[1] 第一個捕獲組所有匹配...
  • PREG_SET_ORDER:$matches[0] 第一次匹配的所有捕獲組,$matches[1] 第二次...
  • PREG_OFFSET_CAPTURE:每個結果包含 [匹配內容, 偏移位置]

3. preg_replace - 替換

mixed preg_replace(
    mixed $pattern,
    mixed $replacement,
    mixed $subject,
    int $limit = -1,
    int &$count = null
)
  • $replacement 可用 $0 $1 引用捕獲組,或 \1 寫法
  • $limit:最大替換次數,-1 = 無限制
  • $count:實際替換次數(引用傳遞)
  • 支持回調函數:preg_replace_callback

4. preg_split - 分割

array preg_split(
    string $pattern,
    string $subject,
    int $limit = -1,
    int $flags = 0
)
  • 標記:PREG_SPLIT_NO_EMPTY 忽略空結果,PREG_SPLIT_DELIM_CAPTURE 保留分隔符,PREG_SPLIT_OFFSET_CAPTURE 返回偏移

實用代碼片段庫

常用驗證模式

<?php
$patterns = [
    'email'       => '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/',
    'mobile_cn'   => '/^1[3-9]\d{9}$/',
    'id_card'     => '/^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/',
    'url'         => '/^https?:\/\/[^\s\/$.?#].[^\s]*$/i',
    'ipv4'        => '/^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/',
    'chinese'     => '/^[\x{4e00}-\x{9fa5}]+$/u',
    'username'    => '/^[a-zA-Z][a-zA-Z0-9_]{3,15}$/',
    'password'    => '/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/',
    'date_iso'    => '/^\d{4}-\d{2}-\d{2}$/',
    'hex_color'   => '/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/',
];
?>

高級替換技巧

<?php
// 1. 回調函數替換:將所有單詞首字母大寫
$text = 'hello world';
echo preg_replace_callback('/\b\w/', function($m) { return strtoupper($m[0]); }, $text);
// Hello World

// 2. 使用命名捕獲組替換(PHP 7.0+)
$date = '2024-01-15';
echo preg_replace('/(?P\d{4})-(?P\d{2})-(?P\d{2})/', '$d/$m/$y', $date);
// 15/01/2024

// 3. 限制替換次數
echo preg_replace('/\s+/', ' ', "a   b   c", 1); // "a b   c"

// 4. 統計替換次數
$count = 0;
preg_replace('/\d/', '*', 'a1b2c3', -1, $count);
echo $count; // 3
?>

Unicode/中文處理最佳實踐

<?php
// 必須加 u 修飾符
$chinese = '你好世界';

// 正確:匹配中文字符
preg_match_all('/[\x{4e00}-\x{9fa5}]/u', $chinese, $m); // 每個漢字單獨匹配

// 正確:匹配中文詞組
preg_match_all('/[\x{4e00}-\x{9fa5}]+/u', $chinese, $m); // ["你好世界"]

// 錯誤:無 u 修飾符會按字節匹配,導致亂碼
// preg_match_all('/[\x{4e00}-\x{9fa5}]+/', $chinese, $m);

// 字符串長度對比
echo strlen($chinese);        // 12 (字節數)
echo mb_strlen($chinese);     // 4 (字符數)
echo preg_match_all('/./u', $chinese); // 4 (正則 Unicode 模式)
?>

性能優化與避坑指南

災難性回溯防範

<?php
// 危險模式:嵌套量詞 + 失敗匹配
// (a+)+b 匹配 "aaaaaaaaaaaaac" 會極其緩慢

// 優化方案:
// 1. 使用佔有優先量詞 (a++)+b
// 2. 使用原子分組 (?>a+)+b
// 3. 重寫邏輯避免嵌套量詞

// 實測對比
$str = str_repeat('a', 20) . 'c';
$dangerous = '/(a+)+b/';
$optimized = '/(?>a+)+b/';

$start = microtime(true);
preg_match($dangerous, $str);
echo "危險: " . (microtime(true) - $start) . "s\n";

$start = microtime(true);
preg_match($optimized, $str);
echo "優化: " . (microtime(true) - $start) . "s\n";
?>

編譯緩存機制

  • PHP 自動緩存最近使用的編譯後正則(約 4096 個)
  • 同一模式重複使用無額外編譯開銷
  • 動態生成模式時注意緩存污染

常用輔助函數

<?php
// preg_quote: 轉義字符串用於正則字面匹配
$search = 'user?name=test&id=1';
$pattern = '/' . preg_quote($search, '/') . '/';
// 結果: /user\?name=test&id=1/

// preg_filter: 僅返回匹配並替換後的元素(類似 array_filter + preg_replace)
$arr = ['apple', 'banana', 'cherry'];
print_r(preg_filter('/^a/', 'A', $arr)); // [0 => 'Apple']

// preg_last_error: 獲取最後一次錯誤代碼
preg_match('/(?<=\d{3})/', 'abc');
echo preg_last_error(); // PREG_ERROR_INTERNAL (數字)
echo preg_last_error_msg(); // "Internal error" (PHP 8+)
?>

總結

PHP PCRE 正則功能強大且符合 Perl 標準,掌握核心函數(match/all/replace/split)、修飾符(特別是 u)、量詞模式、捕獲組引用,配合 Unicode 支持與性能優化技巧,能高效解決 95% 的文本處理需求。複雜解析任務建議組合使用 DOMDocument、JSON 等專用解析器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved