關(guān)于PCRE的介紹以及實現(xiàn)正則表達式功能的所有說明,都可以在官方手冊中看到:正則表達式(兼容 Perl)
一轩拨、認識PCRE
- PCRE 庫是一個實現(xiàn)了與 perl 5 在語法和語義上略有差異的正則表達式模式匹配功能的函數(shù)集。
- PCRE 是 PHP 核心擴展瓶竭,所以總是啟用的。默認情況下疚沐,該擴展使用內(nèi)置的 PCRE library晒他。
- 自PHP 5.3.0 起悉罕, POSIX 正則表達式擴展被廢棄。所以沒有必要研究 POSIX 正則了掌逛。
- PHP 7.0.0 起 PCRE 默認支持 JIT(just-in-time)編譯技術(shù)师逸,PHP 7.0.12 起可以通過 –without-pcre-jit 禁用 PCRE 的 JIT 功能。PHP 的 Windows 版本已內(nèi)建對此擴展的支持豆混。不需要載入額外的擴展來使用這些函數(shù)篓像。PHP 5.3.0 的之前版本,可通過 –without-pcre-regex 配置選項禁用此擴展崖叫。
二遗淳、正則語法
1. 詳細語法參考
- 詳細的正則語法參考:http://php.net/manual/zh/reference.pcre.pattern.syntax.php
- 正則表達式全集:http://tool.oschina.net/uploads/apidocs/jquery/regexp.html
2. 詳細語法參考
字符 | 描述 |
---|---|
\ | 轉(zhuǎn)義符。 |
^ | 匹配輸入字符串的開始位置心傀。 |
$ | 匹配輸入字符串的結(jié)束位置屈暗。 |
* | 匹配前面的子表達式零次或多次。例如,zo*能匹配“z”以及“zoo”养叛。*等價于{0,}种呐。 |
+ | 匹配前面的子表達式一次或多次。 |
? | 匹配前面的子表達式零次或一次弃甥。 |
{n} | 匹配確定的n次爽室。n是一個非負整數(shù)。例如淆攻,“o{2}”不能匹配“Bob”中的“o”阔墩,但是能匹配“food”中的兩個o。 |
{n,} | 至少匹配n次瓶珊。 |
{n,m} | 最少匹配n次且最多匹配m次啸箫。 |
? | 當該字符緊跟在任何一個其他限制符(*,+,?,{n}伞芹,{n,}忘苛,{n,m})后面時,匹配模式是非貪婪的唱较。非貪婪模式盡可能少的匹配所搜索的字符串扎唾,而默認的貪婪模式則盡可能多的匹配所搜索的字符串。例如南缓,對于字符串“oooo”胸遇,“o+?”將匹配單個“o”,而“o+”將匹配所有“o”汉形。 |
. | 匹配除“\n”之外的任何單個字符狐榔。要匹配包括“\n”在內(nèi)的任何字符,請使用像“(.|\n)”的模式获雕。 |
(pattern) | 匹配pattern并獲取這一匹配。 |
x|y | 匹配x或y收捣。例如届案,“z|food”能匹配“z”或“food”“瞻“(z|f)ood”則匹配“zood”或“food”楣颠。 |
[xyz] | 字符集合。匹配所包含的任意一個字符咐蚯。例如童漩,“[abc]”可以匹配“plain”中的“a”。 |
[^xyz] | 負值字符集合春锋。匹配未包含的任意字符矫膨。例如,“[^abc]”可以匹配“plain”中的“p”。 |
[a-z] | 字符范圍侧馅。匹配指定范圍內(nèi)的任意字符危尿。例如,“[a-z]”可以匹配“a”到“z”范圍內(nèi)的任意小寫字母字符馁痴。 |
[^a-z] | 負值字符范圍谊娇。匹配任何不在指定范圍內(nèi)的任意字符。例如罗晕,“[^a-z]”可以匹配任何不在“a”到“z”范圍內(nèi)的任意字符济欢。 |
\b | 匹配一個單詞邊界,也就是指單詞和空格間的位置小渊。例如法褥,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”粤铭。 |
\B | 匹配非單詞邊界挖胃。“er\B”能匹配“verb”中的“er”梆惯,但不能匹配“never”中的“er”酱鸭。 |
\d | 匹配一個數(shù)字字符。等價于[0-9]垛吗。 |
\D | 匹配一個非數(shù)字字符凹髓。等價于[^0-9]。 |
\f | 匹配一個換頁符怯屉。等價于\x0c和\cL蔚舀。 |
\n | 匹配一個換行符。等價于\x0a和\cJ锨络。 |
\r | 匹配一個回車符赌躺。等價于\x0d和\cM。 |
\s | 匹配任何空白字符羡儿,包括空格礼患、制表符、換頁符等等掠归。等價于[ \f\n\r\t\v]缅叠。 |
\S | 匹配任何非空白字符。等價于[^ \f\n\r\t\v]虏冻。 |
\w | 匹配包括下劃線的任何單詞字符肤粱。等價于“[A-Za-z0-9_]”。 |
\W | 匹配任何非單詞字符厨相。等價于“[^A-Za-z0-9_]”领曼。 |
三鸥鹉、PCRE 函數(shù)(本文重點)
1. preg_filter() 執(zhí)行一個正則表達式搜索和替換
- 語法:mixed preg_filter ( mixed
$pattern
, mixed$replacement
, mixed$subject
[, int$limit
= -1 [, int&$count
]] )
說明:preg_filter()等價于preg_replace() 除了它僅僅返回(可能經(jīng)過轉(zhuǎn)化)與目標匹配的結(jié)果。
返回值: 如果subject是一個數(shù)組悯森,返回一個數(shù)組宋舷, 其他情況返回一個字符串。如果沒有找到匹配或者發(fā)生了錯誤瓢姻,當subject是數(shù)組 時返回一個空數(shù)組祝蝠,其他情況返回NULL。
官方示例:
<?php
$subject = array('1', 'a', '2', 'b', '3', 'A', 'B', '4');
$pattern = array('/\d/', '/[a-z]/', '/[1a]/');
$replace = array('A:$0', 'B:$0', 'C:$0');
print_r(preg_filter($pattern, $replace, $subject)); //使用filter
print_r(preg_replace($pattern, $replace, $subject)); //使用replace
/*
返回:
Array
(
[0] => A:C:1
[1] => B:C:a
[2] => A:2
[3] => B:b
[4] => A:3
[7] => A:4
)
Array
(
[0] => A:C:1
[1] => B:C:a
[2] => A:2
[3] => B:b
[4] => A:3
[5] => A
[6] => B
[7] => A:4
)
preg_filter()只返回匹配到的幻碱;preg_replace() 返回所有
*/
2. preg_grep() 返回匹配模式的數(shù)組條目
語法:array preg_grep ( string
$pattern
, array$input
[, int$flags
= 0 ] )說明:返回給定數(shù)組input中與模式pattern 匹配的元素組成的數(shù)組.
-
參數(shù):
- pattern绎狭,要搜索的模式, 字符串形式.
- input,輸入數(shù)組.
- flags褥傍,如果設(shè)置為PREG_GREP_INVERT, 這個函數(shù)返回輸入數(shù)組中與給定模式pattern不匹配的元素組成的數(shù)組
返回值:返回使用input中key做索引的數(shù)組儡嘶。
-
例子:
<?php $array = array("23.32","22","12.009","23.43.43"); print_r(preg_grep("/^(\d+)?\.\d+$/", $array)); //Array ( [0] => 23.32 [2] => 12.009 ) print_r(preg_grep("/^(\d+)?\.\d+$/", $array, PREG_GREP_INVERT)); //Array ( [1] => 22 [3] => 23.43.43 )
3. preg_last_error() 返回最后一個PCRE正則執(zhí)行產(chǎn)生的錯誤代碼
語法:int preg_last_error ( void )
-
返回值:返回最后一次PCRE正則執(zhí)行的錯誤代碼。
- PREG_NO_ERROR 沒有匹配錯誤
- PREG_INTERNAL_ERROR 有PCRE內(nèi)部錯誤
- PREG_BACKTRACK_LIMIT_ERROR 調(diào)用回溯限制超出
- PREG_RECURSION_LIMIT_ERROR 遞歸限制超出
- PREG_BAD_UTF8_ERROR 異常的utf-8數(shù)據(jù)導致
- PREG_BAD_UTF8_OFFSET_ERROR (自 PHP 5.3.0 起) 偏移量與合法的urf-8代碼不匹配
- PREG_JIT_STACKLIMIT_ERROR (自 PHP 7.0.0 起) 因 JIT 椈蟹纾空間限制而失敗
具體錯誤代碼的詳情在上面預定義常量部分蹦狂。
官方示例:
<?php
$a = preg_match('/(?:\D+|<\d+>)*[!?]/', 'foobar foobar foobar');
if (preg_last_error() == PREG_BACKTRACK_LIMIT_ERROR) {
print 'Backtrack limit was exhausted!';
}
// 輸出:Backtrack limit was exhausted!
4. preg_match() 執(zhí)行匹配正則表達式
語法:int preg_match ( string
$pattern
, string$subject
[, array &$matches
[, int$flags
= 0 [, int$offset
= 0 ]]] )說明:搜索subject與pattern給定的正則表達式的一個匹配。
-
參數(shù):
- pattern朋贬,要搜索的模式凯楔,字符串類型。
- subject锦募,輸入字符串摆屯。
- matches,如果提供了參數(shù)matches糠亩,它將被填充為搜索結(jié)果虐骑。
$matches[0]
將包含完整模式匹配到的文本,$matches[1]
將包含第一個捕獲子組匹配到的文本赎线,以此類推廷没。 - flags,可以被設(shè)置為以下標記值:
PREG_OFFSET_CAPTURE垂寥,如果傳遞了這個標記腕柜,對于每一個出現(xiàn)的匹配返回時會附加字符串偏移量(相對于目標字符串的)。 注意:這會改變填充到matches參數(shù)的數(shù)組矫废,使其每個元素成為一個由 第0個元素是匹配到的字符串,第1個元素是該匹配字符串 在目標字符串subject中的偏移量砰蠢。 - offset蓖扑,通常,搜索從目標字符串的開始位置開始台舱÷筛埽可選參數(shù) offset 用于 指定從目標字符串的某個位置開始搜索(單位是字節(jié))潭流。
返回值:preg_match()返回 pattern 的匹配次數(shù)。 它的值將是0次(不匹配)或1次柜去,因為preg_match()在第一次匹配后 將會停止搜索灰嫉。preg_match_all()不同于此,它會一直搜索subject 直到到達結(jié)尾嗓奢。 如果發(fā)生錯誤preg_match()返回 FALSE讼撒。
例子:
<?php
//從URL中獲取主機名稱
preg_match('@^(?:http://)?([^/]+)@i', "http://www.php.net/index.html", $matches);
print_r($matches);
// 輸出 Array ( [0] => http://www.php.net [1] => www.php.net )
//獲取主機名稱的后面兩部分
preg_match('/[^.]+\.[^.]+$/', $matches[1], $matches);
print_r($matches);
// 輸出 Array ( [0] => php.net )
5. preg_match_all() 執(zhí)行一個全局正則表達式匹配
語法:int preg_match_all ( string
$pattern
, string$subject
[, array &$matches
[, int$flags
= PREG_PATTERN_ORDER [, int$offset
= 0 ]]] )說明: 搜索subject中所有匹配pattern給定正則表達式的匹配結(jié)果并且將它們以flag指定順序輸出到matches中。在第一個匹配找到后股耽,子序列繼續(xù)從最后一次匹配位置搜索根盒。
-
參數(shù):
- pattern,要搜索的模式物蝙,字符串形式炎滞。
- subject,輸入字符串诬乞。
- matches册赛,多維數(shù)組,作為輸出參數(shù)輸出所有匹配結(jié)果, 數(shù)組排序通過flags指定震嫉。
- flags森瘪,可以結(jié)合下面標記使用(注意不能同時使用PREG_PATTERN_ORDER和PREG_SET_ORDER)
- PREG_PATTERN_ORDER 結(jié)果排序為matches[1] 保存第一個子組的所有匹配,以此類推责掏。
- PREG_SET_ORDER 結(jié)果排序為matches[1]是包含第二次匹配到的所有匹配(包含子組)的數(shù)組,以此類推换衬。
- PREG_OFFSET_CAPTURE 如果這個標記被傳遞痰驱,每個發(fā)現(xiàn)的匹配返回時會增加它相對目標字符串的偏移量。 注意這會改變matches中的每一個匹配結(jié)果字符串元素瞳浦,使其 成為一個第0個元素為匹配結(jié)果字符串担映,第1個元素為 匹配結(jié)果字符串在subject中的偏移量。
- 如果沒有給定排序標記叫潦,假定設(shè)置為PREG_PATTERN_ORDER蝇完。
- offset,通常矗蕊, 查找時從目標字符串的開始位置開始短蜕。可選參數(shù)offset用于 從目標字符串中指定位置開始搜索(單位是字節(jié))傻咖。
返回值:返回完整匹配次數(shù)(可能是0)朋魔,或者如果發(fā)生錯誤返回FALSE。
例子:
<?php
// \\2是一個后向引用的示例. 這會告訴pcre它必須匹配正則表達式中第二個圓括號(這里是([\w]+))
// 匹配到的結(jié)果. 這里使用兩個反斜線是因為這里使用了雙引號.
$html = "<b>bold text</b><a href=howdy.html>click me</a>";
preg_match_all("/(<([\w]+)[^>]*>)(.*?)(<\/\\2>)/", $html, $matches, PREG_SET_ORDER);
foreach ($matches as $val) {
echo "matched: " . $val[0] . "\n";
echo "part 1: " . $val[1] . "\n";
echo "part 2: " . $val[2] . "\n";
echo "part 3: " . $val[3] . "\n";
echo "part 4: " . $val[4] . "\n\n";
}
/*以上例程會輸出:
matched: <b>bold text</b>
part 1: <b>
part 2: b
part 3: bold text
part 4: </b>
matched: <a href=howdy.html>click me</a>
part 1: <a href=howdy.html>
part 2: a
part 3: click me
part 4: </a> */
6. preg_quote() 轉(zhuǎn)義正則表達式字符
語法:string preg_quote ( string
$str
[, string$delimiter
= NULL ] )-
說明: preg_quote()需要參數(shù) str 并向其中每個正則表達式語法中的字符前增加一個反斜線卿操。 這通常用于你有一些運行時字符串需要作為正則表達式進行匹配的時候警检。
- 正則表達式特殊字符有: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : –
- 注意 / 不是正則表達式特殊字符孙援。
注意:preg_quote() 的應用場景不是用于 preg_replace() 的 $replacement 字符串參數(shù)。
-
參數(shù):
- str扇雕,輸入字符串
- delimiter拓售,如果指定了可選參數(shù) delimiter,它也會被轉(zhuǎn)義镶奉。這通常用于 轉(zhuǎn)義PCRE函數(shù)使用的分隔符础淤。 / 是最常見的分隔符。
返回值:返回轉(zhuǎn)義后的字符串腮鞍。
-
例子:
<?php $keywords = '$40 for a g3/400'; $keywords1 = preg_quote($keywords); echo $keywords1; // 返回 \$40 for a g3/400 echo "<br>"; $keywords2 = preg_quote($keywords, '/'); echo $keywords2; // 返回 \$40 for a g3\/400 // $是正則表達式特殊字符, /被當參數(shù)傳入也轉(zhuǎn)義
7. preg_replace_callback() 執(zhí)行一個正則表達式搜索并且使用一個回調(diào)進行替換
語法:mixed preg_replace_callback ( mixed
$pattern
, callable$callback
, mixed$subject
[, int$limit
= -1 [, int &$count
]] )說明:這個函數(shù)的行為除了 可以指定一個 callback 替代 replacement 進行替換 字符串的計算值骇,其他方面等同于 preg_replace()。
-
參數(shù):
- pattern移国,要搜索的模式吱瘩,可以使字符串或一個字符串數(shù)組。
- callback迹缀, 一個回調(diào)函數(shù)使碾,在每次需要替換時調(diào)用,調(diào)用時函數(shù)得到的參數(shù)是從subject 中匹配到的結(jié)果祝懂∑币。回調(diào)函數(shù)返回真正參與替換的字符串。這是該回調(diào)函數(shù)的簽名:string handler ( array $matches ) 砚蓬。你可能經(jīng)常會需要callback函數(shù)而 僅用于preg_replace_callback()一個地方的調(diào)用矢门。在這種情況下,你可以 使用匿名函數(shù)來定義一個匿名函數(shù)作 為preg_replace_callback()調(diào)用時的回調(diào)灰蛙。 這樣做你可以保留所有 調(diào)用信息在同一個位置并且不會因為一個不在任何其他地方使用的回調(diào)函數(shù)名稱而污染函數(shù)名稱空間祟剔。
- subject,要搜索替換的目標字符串或字符串數(shù)組摩梧。
- limit物延,對于每個模式用于每個 subject 字符串的最大可替換次數(shù)。 默認是-1(無限制)仅父。
- count叛薯,如果指定,這個變量將被填充為替換執(zhí)行的次數(shù)笙纤。
返回值: 如果subject是一個數(shù)組耗溜, preg_replace_callback()返回一個數(shù)組,其他情況返回字符串省容。 錯誤發(fā)生時返回 NULL抖拴。如果查找到了匹配,返回替換后的目標字符串(或字符串數(shù)組)蓉冈, 其他情況subject 將會無變化返回城舞。
官方示例:
<?php
/* 將文本中的年份增加一年 */
$text = "April fools day is 04/01/2002\n";
$text.= "Last christmas was 12/24/2001\n";
// 回調(diào)函數(shù)
function next_year($matches)
{
// 通常: $matches[0]是完成的匹配
// $matches[1]是第一個捕獲子組的匹配
// 以此類推
return $matches[1].($matches[2]+1);
}
$text = preg_replace_callback("|(\d{2}/\d{2}/)(\d{4})|", "next_year", $text);
echo $text;
/*
輸出
April fools day is 04/01/2003
Last christmas was 12/24/2002
*/
8. preg_replace_callback_array() 執(zhí)行一個正則表達式搜索并且使用多個回調(diào)進行替換
語法:mixed preg_replace_callback_array ( array
$patterns_and_callbacks
, mixed$subject
[, int$limit
= -1 [, int &$count
]] )說明:除了回調(diào)函數(shù)是基于每個patterns外,其他方面類似于 preg_replace_callback()寞酿。
-
參數(shù):
- patterns_and_callbacks家夺,參數(shù)(keys)對應回調(diào)函數(shù)(values)的數(shù)組。
- subject伐弹,要搜索替換的目標字符串或字符串數(shù)組拉馋。
- limit,對于每個模式用于每個 subject 字符串的最大可替換次數(shù)惨好。 默認是-1(無限制)煌茴。
- count,如果指定日川,這個變量將被填充為替換執(zhí)行的次數(shù)蔓腐。
返回值:
preg_replace_callback_array() 如果參數(shù)是數(shù)組則會返回一個數(shù)組,否則為字符串龄句。出錯時返回 NULL回论;如果匹配到,會返回一個新的subject-
官方示例:
<?php $subject = 'Aaaaaa Bbb'; preg_replace_callback_array( [ '~[a]+~i' => function ($match) { echo strlen($match[0]), ' matches for "a" found', PHP_EOL; }, '~[b]+~i' => function ($match) { echo strlen($match[0]), ' matches for "b" found', PHP_EOL; } ], $subject ); /* 輸出 6 matches for "a" found 3 matches for "b" found */
9. preg_replace() 執(zhí)行一個正則表達式的搜索和替換
語法:mixed preg_replace ( mixed
$pattern
, mixed$replacement
, mixed$subject
[, int$limit
= -1 [, int &$count
]] )說明:搜索subject中匹配pattern的部分分歇, 以replacement進行替換傀蓉。
-
參數(shù):
- pattern,要搜索的模式职抡≡崃牵可以使一個字符串或字符串數(shù)組。 可以使用一些PCRE修飾符缚甩。
- replacement谱净,用于替換的字符串或字符串數(shù)組。如果這個參數(shù)是一個字符串蹄胰,并且pattern 是一個數(shù)組岳遥,那么所有的模式都使用這個字符串進行替換。如果pattern和replacement 都是數(shù)組裕寨,每個pattern使用replacement中對應的 元素進行替換浩蓉。如果replacement中的元素比pattern中的少, 多出來的pattern使用空字符串進行替換宾袜。replacement中可以包含后向引用\n 或$n捻艳,語法上首選后者。 每個 這樣的引用將被匹配到的第n個捕獲子組捕獲到的文本替換庆猫。
- subject认轨,要進行搜索和替換的字符串或字符串數(shù)組。如果subject是一個數(shù)組月培,搜索和替換回在subject 的每一個元素上進行, 并且返回值也會是一個數(shù)組嘁字。
- limit恩急,每個模式在每個subject上進行替換的最大次數(shù)。默認是 -1(無限)纪蜒。
- count衷恭,如果指定,將會被填充為完成的替換次數(shù)纯续。
返回值: 如果subject是一個數(shù)組随珠, preg_replace()返回一個數(shù)組, 其他情況下返回一個字符串猬错。如果匹配被查找到窗看,替換后的subject被返回,其他情況下 返回沒有改變的 subject倦炒。如果發(fā)生錯誤显沈,返回 NULL 。
-
例子:
<?php $patterns = array ('/(19|20)(\d{2})-(\d{1,2})-(\d{1,2})/', '/^\s*{(\w+)}\s*=/'); $replace = array ('\3/\4/\1\2', '$\1 ='); echo preg_replace($patterns, $replace, '{startDate} = 1999-5-27'); // 輸出: $startDate = 5/27/1999
10. preg_split() 通過一個正則表達式分隔字符串
語法:array preg_split ( string
$pattern
, string$subject
[, int$limit
= -1 [, int$flags
= 0 ]] )說明:通過一個正則表達式分隔給定字符串.
-
參數(shù):
- pattern析校,用于搜索的模式构罗,字符串形式。
- subject智玻,輸入字符串
- limit遂唧,如果指定,將限制分隔得到的子串最多只有l(wèi)imit個吊奢,返回的最后一個 子串將包含所有剩余部分盖彭。limit值為-1, 0或null時都代表”不限制”页滚, 作為php的標準召边,你可以使用null跳過對flags的設(shè)置。
- flags裹驰,可以是任何下面標記的組合(以位或運算 | 組合):
- PREG_SPLIT_NO_EMPTY隧熙,如果這個標記被設(shè)置, preg_split() 將進返回分隔后的非空部分幻林。
- PREG_SPLIT_DELIM_CAPTURE贞盯,如果這個標記設(shè)置了,用于分隔的模式中的括號表達式將被捕獲并返回沪饺。
- PREG_SPLIT_OFFSET_CAPTURE躏敢,如果這個標記被設(shè)置, 對于每一個出現(xiàn)的匹配返回時將會附加字符串偏移量. 注意:這將會改變返回數(shù)組中的每一個元素, 使其每個元素成為一個由第0 個元素為分隔后的子串,第1個元素為該子串在subject 中的偏移量組成的數(shù)組整葡。
返回值:返回一個使用 pattern 邊界分隔 subject 后得到 的子串組成的數(shù)組件余, 或者在失敗時返回 FALSE。
-
例子:
<?php //使用逗號或空格(包含" ", \r, \t, \n, \f)分隔短語 $keywords = preg_split ("/[\s,]+/", "hypertext language, programming"); print_r($keywords); // 輸出 // Array ( [0] => hypertext [1] => language [2] => programming )