之前一篇文章翻譯了perl語言中的遞迴正規表示式. 其實不少語言中的正則都是支援遞迴的, 例如本文要介紹的php正則遞迴. 雖然, 工作中最常用的正規表示式都很」正則」, 只用最基本的語法就能解決85%以上的問題, 而且合理有效地使用普通正則來解決複雜問題也是一門技巧與學問; 但是高階一點的語法的確有它存的價值, 有時不用它還真辦不了事兒; 況且學習正則的樂趣也在於嘗試各種各樣的可能性, 滿足自己無窮無盡的好奇心.
本文內容, 整理自網文finer points odcfotzdf php regular expressions. 其分析過程剝繭抽絲, 絲絲入扣, 值得一讀. 該文系統地列出了php中正規表示式常見特性, 我只摘取其中遞迴部分翻譯整理出來.
正文 例子
什麼時候會用到遞迴正規表示式呢? 當然是待匹配的字串中遞迴地出現某種模式時(貌似廢話). 最經典的例子, 就是遞迴正則處理巢狀括號的問題了. 例子如下.
假設你的文字中包含了正確配對的巢狀括號. 括號的深度可以是無限層. 你想捕獲這樣的括號組.
恕我劇透, 標準答案是這樣的:
複製** **如下:
<?php
$string = "some text (a(b(c)d)e) more text";
if(preg_match("/\(([^()]+|(?r))*\)/",$string,$matches))
?>
其輸出結果是:
複製** **如下:
array
( [0]程式設計客棧 => (a(b(c)d)e)
[1] => e )
可見, 我們所需要的文字, 已經捕獲到$matches[0]中了.
原理 現在思考原理.
上面的正規表示式中的關鍵點是(?r). (?r)的作用就是遞迴地替換它所在的整條正規表示式. 在每次迭代時, php 語法分析器都會將(?r)替換為」\(([^()]+|(?r))*\)「.
因此, 具體到上述的例子, 其正規表示式等價於:
"/\(([^()]+|\(([^()]+|\(([^()]+)*\))*\))*\)/"
但是上面的**只適合深度為3層的括號. 對於未知深度的括號巢狀, 就只好使用這種正則了:
"/\(([^()]+|(?r))*\)/"
它不但能夠匹配無限深度, 還簡化了正規表示式的語法. 功能強大, 語法簡潔.
現在來細看一下"/\(([^()]+|(?r))*\)/"是怎樣匹配"(a(b(c)d)e)"的:
"(c)"這部分被正則式 "\(([^()]+)*\)" 匹配. 請注意, (c) 其實就相當於整個遞迴的乙個縮影, 麻雀雖小五臟俱全, 因此它用到了整個正規表示式.
換言之, 下一步中的(c), 可以使用(?r) 來匹配.
(b(c)d)的匹配過程為:
"\("匹配"(";
"[^()]+"匹配"b";
(?r)匹配"(c)";
"[^()]+"匹配"d";
"\)"匹配")".
根據上面的匹配原理, 不難理解為什麼陣列的第2個元素$matches[1]與'e'等價. 子串'e'是在最後一次匹配迭代中**獲. 匹配過程中, 只有最後一次的捕獲結果才會儲存到陣列中.
rex注: 關於這個特性, 可以自行嘗試一下, 看看使用正則式([a-z]+[0-9]+)+來匹配字串abc123xyz890, 其捕獲結果$1是什麼. 注意, 其結果與 left longest 原理並不衝突.
如果我們只需要捕獲 $matches[0], 可以這樣做:
複製** **如下:
<?php
$string = "some text (a(b(c)d)e) more text";
if(preg_match("/\((?:[^()]+|(?r))*\)/www.cppcns.com",$string,$matches))
?>
產生的結果相同:
複製** **如下:
array
( [0] =>dcfotzd (a(b(c)d)e) )
所做的改動是捕獲括號()改為非捕獲捕獲括號(?:)了.
還可以進一步完善為:
複製** **如下:
<?php
$string = "some text (a(b(c)d)e) more text";
if(preg_match("/\((?>[^()]+|(?r))*\)/",$string,$matches))
?>
這裡我們用到了所謂的一次性模式(rex注: 餘晟先生譯的《精通正規表示式v3.0》中, 謂之」固化分組」. 可參考該書.) php手冊也推薦只要條件允許, 就盡可能使用這種模式, 以便提公升正規表示式的速度.
本文標題: php中的遞迴正則使用說明
本文位址: /wangluo/re/58592.html
jquery中this的使用說明
在使用jquery操作js時,經常整不明白this與 this 抽空仔細測試了一把,記錄下來以供在忘記的時候拉出來參考參考!document ready function this 生成的是什麼 生成的是什麼呢?實際上 jquery 那麼也就是說返回的是乙個jquery的物件。題外話 通常我們為了簡...
this的使用說明
student類中 private string name public void setname string name main函式中 student stu1 newstudent stu1.setname 小冪冪 此時main函式中stu1儲存了student類的記憶體位址,當stu1呼叫s...
解析PHP快取函式的使用說明
flush 重新整理輸出程式快取 for i 0 i 5 i ob start 函式,限定長度,隨時輸出快取 true 開啟,前提 output buffer on ob clear 重新整理 ob end clear 關閉,並重新整理 ob flush 輸出 ob end flush 關閉,並輸出...