久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合

站長資訊網
最全最豐富的資訊網站

PHP正則表達式的效率 回溯與固化分組

先來看下問題。

字符串

復制代碼 代碼如下:
$str = ‘<script>123456</script>’;

正則表達式為

復制代碼 代碼如下:
$strRegex1 = ‘%<script>.+</script>%’;
$strRegex2 = ‘%<script>.+?</script>%’;
$strRegex3 = ‘%<script>(?:(?!</script>).)+</script>%’;

這三個正則,分別會造成幾次回溯呢??
答案:

復制代碼 代碼如下:
$strRegex1 = ‘%<script>.+</script>%’; //9次,記得區別轉義符號。
$strRegex2 = ‘%<script>.+?</script>%’; //5次
$strRegex3 = ‘%<script>(?:(?!</script>).)+</script>%’; //7次

對于第一種貪婪匹配的匹配規則,回溯的9次是正則【】對字符串“”匹配時,構成的回溯,回溯的次數,恰好是字符串的長度。
第二種非貪婪匹配規則,回溯5次,是正則【.+?】對字符串“123456”匹配時構成的回溯。回溯的次數,為字符串長度減去最小次數。也就是6-1=5次。如果正則表達式為【.*?】那么,回溯次數就是6次了。
第三種正則是零寬斷言,或者叫環視。(暫且不說。)
在NFA正則引擎中,回溯是他的靈魂,所以,不管是貪婪,非貪婪,環視等寫法中肯定會有回溯的出現的,這個我們無法避免(用詞不太準確),但是,我們可以減少回溯的次數,或者保護其中一部分匹配的規則不進行回溯。

對于上篇BLOG上提到的鳥哥談到一個非貪婪引起的大量回溯問題,大家可以知道,回溯,確實是浪費資源的罪魁禍首,那么,我們能否不讓其回溯呢?
答案是肯定的,NFA引擎中,有個概念,叫固化分組。引用一下書上的概念

復制代碼 代碼如下:
具體來說,使用「(?>…)」的匹配與正常的匹配并無差別,但是如果匹配進行到此結構之后(也就是,進行到閉括號之后),那么此結構體中的所有備用狀態都會被放棄。也就是說,在固化分組匹配結束時,它已經匹配的文本已經固化為一個單元,只能作為整體而保留或放棄。括號內的子表達式中未嘗試過的備用狀態都不復存在了,所以回溯永遠也不能選擇其中的狀態(至少是,當此結構匹配完成時,“鎖定(locked in)”在其中的狀態)。

那么,固化分組到底有什么用處呢?我們來舉個例子。(找不到合適的例子,俺只好借用一下書上的例子了)
比如要處理一批數據,原來格式為123.456,后來因為浮點數顯示問題,部分數據格式變為123.456000000789這種,,要求做到只保留小數點后面2-3位,但是,最后一位不能為0,這個正則如何寫呢?(下面直接考慮小數點后面的數字),寫出正則之后,我們還要用這個正則去匹配數據,把原來的數據替換成匹配的結果。
首先,我們可以立刻寫出這樣的正則【.dd[1-9]?d*】,PHP代碼為

復制代碼 代碼如下:
$str = preg_replace(‘.(dd[1-9]?)d*’,’\1′,$str); //匹配結果的group1進行反向引用

很明顯,這種寫法,對于部分數據格式為123.456的這種格式,白白的處理了一遍,為了提高效率,我們還要對這個正則進行處理。從123.456這個字符串跟其他的比較一下,我們發現,是疑問123.456這個數據后面沒數字了,所以,白白處理一遍。那好辦,我們對這個正則改造一下,把后面的量詞*改成+,這樣對于123.45 小數點后面1,2位數字的,不會去白白處理,而且,對三位以上數字的,處理正常。其PHP代碼為

復制代碼 代碼如下:
$str = preg_replace(‘.(dd[1-9]?)d+’,’\1′,$str);

好了,這個正則真的沒問題嗎??確定嗎?上篇博文,我們了解了匹配原理,那么,我們也分析一下這個正則的匹配過程吧。
字符串”123.456″,正則表達式為【.(dd[1-9]?)d+】,我們來看下
首先(小數點前123不說了),【.】匹配”.”,匹配成功,把控制權給下一個【d】,【d】匹配“4”成功,把控制權給第二個【d】,這個【d】匹配“5”成功,然后,把控制權給了【[1-9]?】,由于量詞是【?】,正則表達式遵循“量詞優先匹配”,而且,此處是【?】,還會留下一個回溯點。然后匹配”6″成功,然后把控制權給【d+】,【d+】發現后面沒字符了,最遵循“后進先出”規則,回到上一個回溯點,進行匹配,這時,【[1-9]?】會交還出其匹配的字符“6”,【[1-9]?】匹配“6”成功。匹配完成了。大家發現【(dd[1-9]?)】匹配的結果確是”45″,并不是我們想要的“456”,“6”被【d+】匹配去了。那么,我們該如何辦呢? 能否讓【[1-9]?】匹配一旦成功,不進行回溯呢?這就用到了我們上面說的”固化分組”, PHP(preg_replace函數)中使用的正則引擎支持固化分組,我們根據固化分組的寫法,可以把代碼改成如下方式

復制代碼 代碼如下:
$str = preg_replace(‘.(dd(?>[1-9]?))d+’,’\1′,$str);

改成這樣的話,那字符串“123.456“是不符合要求,不會被匹配的。那我們就可以實現我們的要求了。

從上面的例子中,知道了固化分組的作用,那么對于鳥哥BLOG上寫的那個非貪婪的回溯問題,我們能否也對其改造,使得其不回溯呢?
先看下鳥哥給的答案

復制代碼 代碼如下:
/<script>[^<]*</script>/is

鳥哥寫的很精悍。排除“<”之外的所有字符都符合,而且,中間部分不回溯,效率高。可是,如果中間有字符“<“的話(如下代碼)

復制代碼 代碼如下:
<script>
if a < b
</script>

那鳥哥的這個正則就不能匹配,就不能實現我們想要的功能了。
那我們可以根據 固化分組、環視(零寬斷言)來實現這個要求,最后,CFC4N給出的正則以及PHP代碼事例如下

復制代碼 代碼如下:
$reg = ‘%<script>(?>[^<]*)(?>(?!</?script>)<[^<]*)*</script>%is’;
$str = str_pad(“<script>”, 111111, “*”); //字符長度大于PHP回溯限制的100000
$str .= ‘if a < b ; if b > c;</script>’; //隨便加幾個包含 < > 的測試字符
$ret = preg_replace($reg, “OK”, $str);
print_r($ret); //打印結果 OK,證明匹配正確
var_dump(preg_last_error()); //上一次匹配錯誤。其輸出為 int(0)

嗨,同學,你看明白了嗎?

以上為小菜CFC4N的愚文,如有錯誤,歡迎指出。

贊(0)
分享到: 更多 (0)
?
網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
久久精品五月,日韩不卡视频在线观看,国产精品videossex久久发布 ,久久av综合
你懂的国产精品永久在线| 欧美日韩精品免费观看视频完整| 久久都是精品| 精品一区二区三区免费看| 欧美三区不卡| 久久国际精品| 日韩精品一区二区三区中文在线 | 国内精品伊人| 97人人精品| 国产麻豆久久| 在线成人直播| 亚洲另类黄色| 欧美久久香蕉| 欧美日韩午夜| 精品一区二区三区中文字幕在线| 久久的色偷偷| 日韩av自拍| 日韩不卡视频在线观看| 色88888久久久久久影院| 99热国内精品| 久久国产精品99国产| 亚洲日韩中文字幕一区| 欧美一区二区三区久久| 国产一区丝袜| 五月精品视频| 亚洲综合色婷婷在线观看| 国产丝袜一区| 国产福利片在线观看| 国产一区清纯| 日韩高清在线观看一区二区| 欧美激情精品| 久久久精品网| 亚洲精品日韩久久| 国产精品一线天粉嫩av| 日韩成人a**站| 精品1区2区3区4区| 日韩高清一区二区| 国产成人免费视频网站视频社区| 日韩精品午夜| 日本不卡视频一二三区| 国产精品99视频| 久久高清一区| 麻豆精品在线| 午夜精品一区二区三区国产| 日韩一二三区在线观看| 欧美激情另类| 蜜臀久久99精品久久久画质超高清 | www.九色在线| 亚洲女同中文字幕| 青青草国产成人99久久| 国产成人免费精品| 丝袜诱惑制服诱惑色一区在线观看 | 天堂√8在线中文| 视频在线在亚洲| 国产精品欧美日韩一区| 免费不卡中文字幕在线| 91精品在线免费视频| 88xx成人免费观看视频库| 亚洲精品三级| 欧洲av不卡| 日本视频一区二区| 久久九九精品| 日韩激情啪啪| 欧美1级日本1级| 国产精品色在线网站| 红桃视频欧美| 麻豆理论在线观看| 久久国产三级| 红桃视频国产精品| 卡一精品卡二卡三网站乱码| 免费在线观看视频一区| 日韩免费一区| 91成人福利| 欧美日韩国产欧| 精品国产乱码| 日本在线观看不卡视频| 免费视频国产一区| 老司机精品在线| 在线精品国产亚洲| 成人看片网站| 国产精品1luya在线播放| 鲁大师成人一区二区三区| 欧美日韩视频网站| 麻豆精品久久| 蜜桃av一区二区在线观看| 日韩欧美另类一区二区| 国产精品男女| 日韩高清一区二区| 99在线精品免费视频九九视| 福利在线免费视频| 麻豆免费精品视频| 欧美自拍一区| 伊人www22综合色| 一区免费在线| 日韩国产一区二区| 精品一区二区三区在线观看视频| 日本精品一区二区三区在线观看视频| 亚洲激情另类| 亚洲天堂黄色| 97精品视频在线看| 精品国产麻豆| 久久精品国产99| 国产麻豆一区二区三区| 亚欧洲精品视频在线观看| 久久福利精品| 日韩一级网站| 日本精品影院| 日韩国产激情| 久久影院午夜精品| 韩国一区二区三区视频| 卡一卡二国产精品| 乱一区二区av| 久久精品三级| 精品香蕉视频| 久久只有精品| 久久精品网址| 精品国产a一区二区三区v免费| 国产精品久久久久久久久久齐齐| 91嫩草精品| 国产日韩一区二区三区在线| 青青伊人久久| 国产精品一区二区精品| 国产精品一级| 久久国产精品美女| 狠狠久久伊人中文字幕| 国产精选在线| 肉色欧美久久久久久久免费看 | 欧洲激情综合| 日韩一区二区免费看| 欧美综合国产| 亚洲精品极品| 色综合视频一区二区三区日韩 | 黄色欧美在线| 日韩欧美1区| 久久精品亚洲人成影院| 久久亚洲成人| 欧美特黄一区| 爽好久久久欧美精品| 日韩激情一二三区| 欧美黄页在线免费观看| 成人精品高清在线视频| 天堂日韩电影| 午夜亚洲一区| 亚洲字幕久久| 国产精品亚洲综合色区韩国| 老鸭窝一区二区久久精品| 亚洲国产福利| 国产精品99一区二区| 欧美在线综合| 国产麻豆一区二区三区| 嫩草伊人久久精品少妇av杨幂 | 久久99久久久精品欧美| 精品中国亚洲| 亚洲电影有码| 免费在线视频一区| 国产精品日本一区二区三区在线| 精品久久97| 免费黄色成人| 蜜桃一区二区三区在线观看| 久久亚洲影院| 国产麻豆一区二区三区精品视频| 久久这里只有| 日本高清不卡一区二区三区视频| 亚洲欧美成人综合| 亚洲深深色噜噜狠狠爱网站| 日韩精品一区二区三区中文| 欧美一区久久| 国产传媒在线观看| 久久亚洲精品伦理| 国产精品一页| 日韩在线看片| 日韩影院精彩在线| 欧美激情麻豆| 欧美天堂亚洲电影院在线观看| 日韩毛片网站| 国产成人精品亚洲线观看| 婷婷成人基地| 欧美日韩一区二区国产| 高潮久久久久久久久久久久久久| 亚洲天堂久久| 蜜芽一区二区三区| 免费一级欧美片在线观看网站| 欧洲精品一区二区三区| 蜜臀av在线播放一区二区三区| 国产精品xxx在线观看| 久久精品国产大片免费观看| 中文字幕av一区二区三区人 | 免费人成在线不卡| 久久精品免视看国产成人| 亚洲一级二级| 91精品视频一区二区| 久久久久久黄| 蜜桃视频免费观看一区| 国产精品天堂蜜av在线播放| 欧美手机在线| 国产亚洲人成a在线v网站| 亚洲网站视频| 欧美激情久久久久久久久久久| 一区在线免费| 欧美aⅴ一区二区三区视频|