PHP中的正則表達(dá)式實(shí)例詳解
最近使用 PHP 寫了一個(gè)應(yīng)用,主要是正則表達(dá)式的處理,趁機(jī)系統(tǒng)性的學(xué)習(xí)了相應(yīng)知識(shí)。
這篇文章的寫作方式不是講理論,而是通過具體的例子來了解正則,這樣也更有實(shí)踐性,在此基礎(chǔ)上再去看正則表達(dá)式的基本概念會(huì)更有收獲。
禁止分組的捕獲
在正則中分組很有用,可以定義子模式,然后可以通過后向引用來引用分組的內(nèi)容,但是有的時(shí)候僅僅想通過分組來進(jìn)行范圍定義,而不想被分組來捕獲,通過一個(gè)例子就能明白:
$str = "http://www.google.com"; $preg= "/http:\/\/\w+\.\w+.(?:net|com|cn)+/is"; $preg2= "/http:\/\/\w+\.\w+.(net|com|cn)+/is"; preg_match($preg,$str,$arr); preg_match($preg2,$str,$arr2);
當(dāng)模式中出現(xiàn)?:表示這個(gè)括號(hào)的分組不會(huì)被引用,運(yùn)行下例子就能明白。
preg_match() 和 preg_match_all() 的區(qū)別
preg_match() 在匹配模式的時(shí)候匹配到一次就結(jié)束,而 preg_match_all() 則進(jìn)行全局匹配,通過一個(gè)例子就能明白:
$str='hello world china'; $preg="/\w+\s/is"; preg_match($preg,$str,$arr); print_r($arr); preg_match_all($preg,$str,$arr); print_r($arr);
正確理解 $ 和 ^
先說一個(gè)正則,為了匹配是否是手機(jī)號(hào):
$str = "13521899942a";
$preg="/1[\d]{3,15}/is";
if (preg_match($preg,$str,$arr)) {
echo "ok";
}
雖然字符串中有一個(gè)英文字母,但是這個(gè)子模式卻匹配了,原因就在于模式匹配到后就結(jié)束了,不會(huì)再去尋找英文字母,為了解決這問題 $ 和 ^ 就發(fā)揮作用了,比如讓字符串的開始和結(jié)尾必須匹配一定的模式,修改如下:
$str = "13521899942a";
$preg="/1[\d]{3,15}$/is";
if (preg_match($preg,$str,$arr)) {
echo "ok";
}
$ 和 ^ 的跨行模式
默認(rèn)的情況下,$ 和 ^ 只會(huì)匹配完整段落的開始和結(jié)尾,但是通過改變選項(xiàng),允許匹配文本的每一行的開始和結(jié)尾,通過下面的例子就能明白
$str='hello world'; $preg='/\w+$/ism';//$preg='/(?m)\w+$/is'; preg_match_all($preg,$str,$arr); print_r($arr);
分組命名
在正則中通過括號(hào)分組后,可以使用 \1,\2 這樣的數(shù)字進(jìn)行后向引用,但是假如正則中模式太多,在使用的時(shí)候就會(huì)比較混亂,這時(shí)候可以采用分組命名來進(jìn)行引用,看個(gè)例子:
$str ="email:ywdblog@gmail.com;";
preg_match("/email:(?<email>\w+?)/is", $str, $matches);
echo $matches["email"] . "_" . $matches['no'];
懶惰模式
正則在匹配的時(shí)候是貪婪的,只要符合模式就會(huì)一直匹配下去,下面的例子,匹配到的文本是 <h2>hello</h2><h2>world</h2>
$str = "<h2>hello</h2><h2>world</h2>"; $preg = "/<h2>.*<\/h2>/is"; preg_match($preg,$str,$arr); print_r($arr);
通過改變一個(gè)選項(xiàng)可以修改為懶惰模式,就是一旦匹配到就中止,修改代碼如下:
$str = "<h2>hello</h2><h2>world</h2>"; $preg = "/<h2>.*?<\/h2>/is"; preg_match($preg,$str,$arr); print_r($arr);
進(jìn)一步理解 preg_match_all()
通過這函數(shù)的最后一個(gè)參數(shù),能夠返回不同形式的數(shù)組:
$str= 'jiangsu (nanjing) nantong guangdong (guangzhou) zhuhai beijing (tongzhou) haidian'; $preg = '/^\s*+([^(]+?)\s\(([^)]+)\)\s+(.*)$/m'; preg_match_all($preg,$str,$arr,PREG_PATTERN_ORDER); print_r($arr); preg_match_all($preg,$str,$arr,PREG_SET_ORDER); print_r($arr);
強(qiáng)大的正則替換回調(diào)
雖然 preg_replace() 函數(shù)能完成大多數(shù)的替換,但是假如你想更好的控制,可以使用回調(diào),不用多說看例子:
$str = "china hello world";
$preg = '/\b(\w+)(\w)\b/';
function fun($m){
return $m[1].strtoupper($m[2]);
}
echo preg_replace_callback($preg,"fun",$str);
在這一點(diǎn)上,PHP 比 Python 強(qiáng)大的多,Python 中沒有正則回調(diào),不過可以使用閉包的方式解決,可看我以前的文章。
preg_quote()
這個(gè)函數(shù)類似于 Python 中的 re.compile() 函數(shù),假如在模式中一些元字符僅僅想表達(dá)字符的本身含義,可以轉(zhuǎn)義,但是假如在模式中寫太多的轉(zhuǎn)義,會(huì)顯得很混亂,可以使用這個(gè)函數(shù)來統(tǒng)一轉(zhuǎn)義:
$str = '\\*china*world';
$preg = "\*china";
$preg = preg_quote($preg);
echo $preg;
preg_match( "/{$preg}/is",$str,$arr);
print_r($arr);
向前查找 ?= 的妙用
用英文解釋可能比較貼切:
The "?=" combination means "the next text must be like this". This construct doesn't capture the text.
(1)這個(gè)例子可以獲取 URL 中的協(xié)議部分,比如 https,ftp,注意 ?: 后面的部分不在返回的內(nèi)容中。
$str = "http://www.google.com"; $str = "https://www.google.com"; $preg = '/[a-z]+(?=:)/'; preg_match($preg,$str,$arr); print_r($arr);
(2)"invisible" 分隔符
也叫 “zero-width” 分隔符,參考下面的例子:
$str = ("chinaWorldHello");
$preg = "/(?=[A-Z])/";
$arr = preg_split($preg,$str);
print_r($arr);
(3)匹配強(qiáng)密碼
instead of specifying the order that things should appear, it's saying that it must appear but we're not worried about the order.
The first grouping is (?=.{8,}). This checks if there are at least 8 characters in the string. The next grouping (?=.[0-9]) means "any alphanumeric character can happen zero or more times, then any digit can happen". So this checks if there is at least one number in the string. But since the string isn't captured, that one digit can appear anywhere in the string. The next groupings (?=.[a-z]) and (?=.[A-Z]) are looking for the lower case and upper case letter accordingly anywhere in the string.
$str= "HelloWorld2016";
if (preg_match("/^.*(?=.{8,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$/", $str,$arr)){
print_r($arr);
}
向后查找 ?<=
?<= 表示假如匹配到特定字符,則返回該字符后面的內(nèi)容。
?= 表示假如匹配到特定字符,則返回該字符前面的內(nèi)容。
$str = 'chinadhello'; $preg = '/(?<=a)d(?=h)/'; preg_match($preg, $str, $arr); print_r($arr);
好了,今天的教程就先到這里,有什么問題大家可以留言,我們來討論下
相關(guān)文章
laravel框架實(shí)現(xiàn)為 Blade 模板引擎添加新文件擴(kuò)展名操作示例
這篇文章主要介紹了laravel框架實(shí)現(xiàn)為 Blade 模板引擎添加新文件擴(kuò)展名操作,結(jié)合實(shí)例形式詳細(xì)分析了laravel框架Blade 模板引擎添加新文件擴(kuò)展名具體操作步驟與相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2020-01-01
thinkPHP5.0框架驗(yàn)證碼調(diào)用及點(diǎn)擊圖片刷新簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了thinkPHP5.0框架驗(yàn)證碼調(diào)用及點(diǎn)擊圖片刷新簡(jiǎn)單實(shí)現(xiàn)方法,結(jié)合簡(jiǎn)單示例形式分析了thinkPHP5框架驗(yàn)證碼相關(guān)配置、后臺(tái)驗(yàn)證、前臺(tái)刷新等操作技巧,需要的朋友可以參考下2018-09-09
ThinkPHP后臺(tái)首頁(yè)index使用frameset時(shí)的注意事項(xiàng)分析
這篇文章主要介紹了ThinkPHP后臺(tái)首頁(yè)index使用frameset時(shí)的注意事項(xiàng),需要的朋友可以參考下2014-08-08
laravel學(xué)習(xí)筆記之模型事件的幾種用法示例
這篇文章主要給大家介紹了關(guān)于laravel學(xué)習(xí)筆記之模型事件用法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用laravel具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考借鑒,下面來跟著小編一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08
PHP+Jquery與ajax相結(jié)合實(shí)現(xiàn)下拉淡出瀑布流效果【無需插件】
這篇文章主要介紹了PHP+Jquery與ajax相結(jié)合實(shí)現(xiàn)下拉淡出瀑布流效果【無需插件】的相關(guān)資料,需要的朋友可以參考下2016-05-05
基于ThinkPHP實(shí)現(xiàn)的日歷功能實(shí)例詳解
這篇文章主要介紹了基于ThinkPHP實(shí)現(xiàn)的日歷功能,結(jié)合實(shí)例形式詳細(xì)分析了基于thinkPHP實(shí)現(xiàn)日歷功能的相關(guān)界面布局、數(shù)據(jù)庫(kù)操作與日期時(shí)間運(yùn)算相關(guān)技巧,需要的朋友可以參考下2017-04-04

