正則匹配原理之 逆序環(huán)視深入 .
說明:部分內(nèi)容有待進(jìn)一步研究和修正,因?yàn)樽罱ぷ魈Γ瑫簳r抽不出時間來,未研究過的可以跳過這一篇,想研究的不要被我的思路所左右了,有研究清楚的還請指正
1、問題引出
前幾天在CSDN論壇遇到這樣一個問題:
var str="8912341253789";
需要將這個字符串中的重復(fù)的數(shù)字給去掉,也就是結(jié)果89123457。
首先需要說明的是,這種需求并不適合用正則來實(shí)現(xiàn),至少,正則不是最好的實(shí)現(xiàn)方式。
這個問題本身不是本文討論的重點(diǎn),本文所要討論的,主要是由這一問題的解決方案而引出的另一個正則匹配原理問題。
先看一下針對這一問題本身給出的解決方案。
string str = "8912341253789"; Regex reg = new Regex(@"((\d)\d*?)\2"); while (str != (str = reg.Replace(str, "$1"))) { } richTextBox2.Text = str; /*--------輸出-------- 89123457 */
基于此有朋友提出另一個疑問,為什么使用下面的正則沒有效果
“(?<=(?<value>\d).*?)\k<value>”
由此也引出本文所要討論的逆序環(huán)視更深入的一些細(xì)節(jié),涉及到逆序環(huán)視的匹配原理和匹配過程。前面的兩篇博客中雖然也有介紹,但還不夠深入,參考 正則基礎(chǔ)之——環(huán)視 和 正則應(yīng)用之——逆序環(huán)視探索 。本文將以逆序環(huán)視和反向引用結(jié)合這種復(fù)雜應(yīng)用場景,對逆序環(huán)視進(jìn)行深入探討。
先把問題簡化和抽象一下,上面的正則中用到了命名捕獲組和命名捕捉組的反向引用,這在一定程度上增加了問題的復(fù)雜度,寫成普通捕獲組,并且用“\d”代替范圍過大的“.”,如下
“(?<=(\d)\d*?)\1”
需要匹配的字符串,抽象一下,取兩種典型字符串如下。
源字符串一:878
源字符串二:9878
與上面正則表達(dá)式類似,正則表達(dá)式相應(yīng)的也有四種形式
正則表達(dá)式一:(?<=(\d)\d*)\1
正則表達(dá)式二:(?<=(\d)\d*?)\1
正則表達(dá)式三:(?<=(\d))\d*\1
正則表達(dá)式四:(?<=(\d))\d*?\1
先看一下匹配結(jié)果:
string[] source = new string[] {"878", "9878" }; List<Regex> regs = new List<Regex>(); regs.Add(new Regex(@"(?<=(\d)\d*)\1")); regs.Add(new Regex(@"(?<=(\d)\d*?)\1")); regs.Add(new Regex(@"(?<=(\d))\d*\1")); regs.Add(new Regex(@"(?<=(\d))\d*?\1")); foreach (string s in source) { foreach (Regex r in regs) { richTextBox2.Text += "源字符串: " + s.PadRight(8, ' '); richTextBox2.Text += "正則表達(dá)式: " + r.ToString().PadRight(18, ' '); richTextBox2.Text += "匹配結(jié)果: " + r.Match(s).Value + "\n------------------------\n"; } richTextBox2.Text += "------------------------\n"; }
/*--------輸出--------
源字符串: 878 正則表達(dá)式: (?<=(\d)\d*)\1 匹配結(jié)果: 8
------------------------
源字符串: 878 正則表達(dá)式: (?<=(\d)\d*?)\1 匹配結(jié)果:
------------------------
源字符串: 878 正則表達(dá)式: (?<=(\d))\d*\1 匹配結(jié)果: 78
------------------------
源字符串: 878 正則表達(dá)式: (?<=(\d))\d*?\1 匹配結(jié)果: 78
------------------------
------------------------
源字符串: 9878 正則表達(dá)式: (?<=(\d)\d*)\1 匹配結(jié)果:
------------------------
源字符串: 9878 正則表達(dá)式: (?<=(\d)\d*?)\1 匹配結(jié)果:
------------------------
源字符串: 9878 正則表達(dá)式: (?<=(\d))\d*\1 匹配結(jié)果: 78
------------------------
源字符串: 9878 正則表達(dá)式: (?<=(\d))\d*?\1 匹配結(jié)果: 78
------------------------
------------------------
*/
這個結(jié)果也許會出乎很多人的意料之外,剛開始接觸這個問題時,我也一樣感到迷惑,放了兩天后,才靈機(jī)一觸,想通了問題的關(guān)鍵所在,下面將展開討論。
在此之前,可能還需要做兩點(diǎn)說明:
1、 下面討論的話題已經(jīng)與本文開始提到的問題沒有多大關(guān)聯(lián)了,最初的問題主要是為了引出本文的話題,問題本身不在討論范圍之內(nèi),而本文也主要是純理論的探討。
2、 本文適合有一定正則基礎(chǔ)的讀者。如果您對上面幾個正則的匹配結(jié)果和匹配過程感到費(fèi)解,沒關(guān)系,下面就將為您解惑;但是如果您對上面幾個正則中元字符和語法代表的意義都不清楚的話,還是先從基礎(chǔ)看起吧。
2、逆序環(huán)視匹配原理深入
正則表達(dá)式一:(?<=(\d)\d*)\1
正則表達(dá)式二:(?<=(\d)\d*?)\1
正則表達(dá)式三:(?<=(\d))\d*\1
正則表達(dá)式四:(?<=(\d))\d*?\1
上面的幾個正則表達(dá)式,可以最終抽象為“(?<=SubExp1)SubExp2”這樣的表達(dá)式,在做逆序環(huán)視原理分析時,根據(jù)“SubExp1”的特點(diǎn),可以歸納為三類:
1、 逆序環(huán)視中的子表達(dá)式“SubExp1”長度固定,正則表達(dá)式三和四屬于這一類,當(dāng)然,這一類里是包括“?”這一量詞的,但也僅限于這一個量詞。
2、 逆序環(huán)視中的子表達(dá)式“SubExp1”長度不固定,其中包含忽略優(yōu)先量詞,如“*?”、“+?”、“{m,}?”等,也就是通常所說的非貪婪模式,正則表達(dá)式二屬于這一類。
3、 逆序環(huán)視中的子表達(dá)式“SubExp1”長度不固定,其中包含匹配優(yōu)先量詞,“*”、“+”、“{m,}”等,也就是通常所說的貪婪模式,正則表達(dá)式一屬于這一類。
下面針對這三類正則表達(dá)式進(jìn)行匹配過程的分析。
2.1 固定長度子表達(dá)式匹配過程分析
2.1.1 源字符串一 + 正則表達(dá)式三匹配過程
源字符串一:878
正則表達(dá)式三:(?<=(\d))\d*\1
首先在位置0處開始嘗試匹配,由“(?<=(\d))”取得控制權(quán),長度固定,只有一位,由位置0處向左查找一位,失敗,“(?<=(\d))”匹配失敗,導(dǎo)致第一輪匹配嘗試失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置1處嘗試匹配,控制權(quán)交給“(?<=(\d))”,向左查找一位,接著將控制權(quán)交給“(\d)”,更進(jìn)一步的將控制權(quán)交給“\d”。“\d”取得控制權(quán)后,向右嘗試匹配,匹配“8”成功,此時“(?<=(\d))”匹配成功,匹配結(jié)果為位置1,捕獲組1匹配到的內(nèi)容就是“8”,控制權(quán)交給“\d*”。由于“\d*”為貪婪模式,會優(yōu)先嘗試匹配位置1后面的“7”和“8”,匹配成功,記錄回溯狀態(tài),控制權(quán)交給“\1”。由于前面捕獲組1捕獲到的內(nèi)容是“8”,所以“\1”要匹配到“8”才能匹配成功,而此時已到達(dá)字符串結(jié)尾處,匹配失敗,“\d*”回溯,讓出最后的字符“8”,再將控制權(quán)交給“\1”, 由“\1”匹配最后的“8”成功,此時整個表達(dá)式匹配成功。由于“(?<=(\d))”只匹配位置,不占有字符,所以整個表達(dá)式匹配到的結(jié)果為“78”,其中“\d*”匹配到的是“7”,“\1”匹配到的是“8”。
2.1.2 源字符串二 + 正則表達(dá)式三匹配過程
源字符串二:9878
正則表達(dá)式三:(?<=(\d))\d*\1
這一組合的匹配過程,與2.1.1節(jié)的匹配過程基本類似,只不過多了一輪匹配嘗試而已,這里不再贅述。
2.1.3 源字符串一 + 正則表達(dá)式四匹配過程
源字符串一:878
正則表達(dá)式四:(?<=(\d))\d*?\1
首先在位置0處開始嘗試匹配,由“(?<=(\d))”取得控制權(quán),長度固定,只有一位,由位置0處向左查找一位,失敗,“(?<=(\d))”匹配失敗,導(dǎo)致第一輪匹配嘗試失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置1處嘗試匹配,控制權(quán)交給“(?<=(\d))”,向左查找一位,接著將控制權(quán)交給“(\d)”,更進(jìn)一步的將控制權(quán)交給“\d”。“\d”取得控制權(quán)后,向右嘗試匹配,匹配“8”成功,此時“(?<=(\d))”匹配成功,匹配結(jié)是果為位置1,捕獲組1匹配到的內(nèi)容就是“8”,控制權(quán)交給“\d*?”。由于“\d*?”為非貪婪模式,會優(yōu)先嘗試忽略匹配,記錄回溯狀態(tài),控制權(quán)交給“\1”。由于前面捕獲組1捕獲到的內(nèi)容是“8”,所以“\1”要匹配到“8”才能匹配成功,而此時位置1后面的字符是“7”,匹配失敗,“\d*?”回溯,嘗試匹配位置1后面的字符“7”,再將控制權(quán)交給“\1”, 由“\1”匹配最后的“8”成功,此時整個表達(dá)式匹配成功。由于“(?<=(\d))”只匹配位置,不占有字符,所以整個表達(dá)式匹配到的結(jié)果為“78”,其中“\d*?”匹配到的是“7”,“\1”匹配到的是最后的“8”。
這與2.1.1節(jié)組合的匹配過程基本一致,只不過就是“\d*”和“\d*?”匹配與回溯過程有所區(qū)別而已。
2.1.4 源字符串二 + 正則表達(dá)式四匹配過程
源字符串二:9878
正則表達(dá)式四:(?<=(\d))\d*?\1
這一組合的匹配過程,與2.1.3節(jié)的匹配過程基本類似,這里不再贅述。
2.2 非貪婪模式子表達(dá)式匹配過程分析
2.2.1 源字符串一 + 正則表達(dá)式二匹配過程
源字符串一:878
正則表達(dá)式二:(?<=(\d)\d*?)\1
首先在位置0處開始嘗試匹配,由“(?<=(\d)\d*?)”取得控制權(quán),長度不固定,至少一位,由位置0處向左查找一位,失敗,“(?<=(\d)\d*?)”匹配失敗,導(dǎo)致第一輪匹配嘗試失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置1處嘗試匹配,控制權(quán)交給“(?<=(\d)\d*?)”,向左查找一位,接著將控制權(quán)交給“(\d)”,更進(jìn)一步的將控制權(quán)交給“\d”。“\d”取得控制權(quán)后,向右嘗試匹配,匹配“8”成功,將控制權(quán)交給“\d*?”,由于“\d*?”為非貪婪模式,會優(yōu)先嘗試忽略匹配,即不匹配任何內(nèi)容,并記錄回溯狀態(tài),此時“(\d)\d*?”匹配成功,那么“(?<=(\d)\d*?)”也就匹配成功,匹配結(jié)果為位置1,由于此處的子表達(dá)式“(\d)\d*?”為非貪婪模式,取得一個成功匹配項(xiàng)后,即交出控制權(quán),同時丟棄所有回溯狀態(tài)。由于前面捕獲組1捕獲到的內(nèi)容是“8”,所以“\1”要匹配到“8”才能匹配成功,而此時位置1后面的字符是“7”,此時已無可供回溯的狀態(tài),整個表達(dá)式在位置1處匹配失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置2處嘗試匹配,控制權(quán)交給“(?<=(\d)\d*?)”,向左查找一位,接著將控制權(quán)交給“(\d)”,更進(jìn)一步的將控制權(quán)交給“\d”。“\d”取得控制權(quán)后,向右嘗試匹配,匹配“7”成功,將控制權(quán)交給“\d*?”,由于“\d*?”為非貪婪模式,會優(yōu)先嘗試忽略匹配,即不匹配任何內(nèi)容,并記錄回溯狀態(tài),此時“(\d)\d*?”匹配成功,那么“(?<=(\d)\d*?)”也就匹配成功,匹配結(jié)果為位置2,由于此處的子表達(dá)式“(\d)\d*?”為非貪婪模式,取得一個成功匹配項(xiàng)后,即交出控制權(quán),同時丟棄所有回溯狀態(tài)。由于前面捕獲組1捕獲到的內(nèi)容是“7”,所以“\1”要匹配到“7”才能匹配成功,而此時位置2后面的字符是“7”,此時已無可供回溯的狀態(tài),整個表達(dá)式在位置2處匹配失敗。
位置3處的匹配過程也同樣道理,最后“\1”因無字符可匹配,導(dǎo)致整個表達(dá)式匹配失敗。
此時已嘗試了字符串所有位置,均匹配失敗,所以整個表達(dá)式匹配失敗,未取得任何有效匹配結(jié)果。
2.2.2 源字符串二 + 正則表達(dá)式二匹配過程
源字符串一:9878
正則表達(dá)式二:(?<=(\d)\d*?)\1
這一組合的匹配過程,與2.2.1節(jié)的匹配過程基本類似,這里不再贅述。
2.3 貪婪模式子表達(dá)式匹配過程分析
2.3.1 源字符串一 + 正則表達(dá)式一匹配過程
源字符串一:878
正則表達(dá)式二:(?<=(\d)\d*)\1
首先在位置0處開始嘗試匹配,由“(?<=(\d)\d*)”取得控制權(quán),長度不固定,至少一位,由位置0處向左查找一位,失敗,“(?<=(\d)\d*)”匹配失敗,導(dǎo)致第一輪匹配嘗試失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置1處嘗試匹配,控制權(quán)交給“(?<=(\d)\d*)”,向左查找一位,接著將控制權(quán)交給“(\d)”,更進(jìn)一步的將控制權(quán)交給“\d”。“\d”取得控制權(quán)后,向右嘗試匹配,匹配“8”成功,將控制權(quán)交給“\d*”,由于“\d*”為貪婪模式,會優(yōu)先嘗試匹配,并記錄回溯狀態(tài),但此時已沒有可用于匹配的字符,所以匹配失敗,回溯,不匹配任何內(nèi)容,丟棄回溯狀態(tài),此時“(\d)\d*”匹配成功,匹配內(nèi)容為“8”,那么“(?<=(\d)\d*)”也就匹配成功,匹配結(jié)果是位置1,由于此處的子表達(dá)式為貪婪模式,“(\d)\d*”取得一個成功匹配項(xiàng)后,需要查找是否還有更長匹配,找到最長匹配后,才會交出控制權(quán)。再向左查找,已沒有字符,“8”已是最長匹配,此時交出控制權(quán),同時丟棄所有回溯狀態(tài)。由于前面捕獲組1捕獲到的內(nèi)容是“8”,所以“\1”要匹配到“8”才能匹配成功,而此時位置1后面的字符是“7”,此時已無可供回溯的狀態(tài),整個表達(dá)式在位置1處匹配失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置2處嘗試匹配,控制權(quán)交給“(?<=(\d)\d*)”,向左查找一位,接著將控制權(quán)交給“(\d)”,更進(jìn)一步的將控制權(quán)交給“\d”。“\d”取得控制權(quán)后,向右嘗試匹配,匹配“7”成功,將控制權(quán)交給“\d*”,由于“\d*”為貪婪模式,會優(yōu)先嘗試匹配,并記錄回溯狀態(tài),但此時已沒有可用于匹配的字符,所以匹配失敗,回溯,不匹配任何內(nèi)容,丟棄回溯狀態(tài),此時“(\d)\d*”匹配成功,匹配內(nèi)容為“7”,那么“(?<=(\d)\d*)”也就匹配成功,匹配結(jié)果是位置2,由于此處的子表達(dá)式為貪婪模式,“(\d)\d*”取得一個成功匹配項(xiàng)后,需要查找是否還有更長匹配,找到最長匹配后,才會交出控制權(quán)。再向左查找,由位置0處向右嘗試匹配,“\d”取得控制權(quán)后,匹配位置0處的“8”成功,將控制權(quán)交給“\d*”,由于“\d*”為貪婪模式,會優(yōu)先嘗試匹配,并記錄回溯狀態(tài),匹配位置1處的“7”成功,此時“(\d)\d*”匹配成功,那么“(\d)\d*”又找到了一個成功匹配項(xiàng),匹配內(nèi)容為“87”,其中捕獲組1匹配到的是“8”。再向左查找,已沒有字符,“87”已是最長匹配,此時交出控制權(quán),同時丟棄所有回溯狀態(tài)。由于前面捕獲組1捕獲到的內(nèi)容是“8”,所以“\1”匹配位置2處的“8”匹配成功,此時整個有達(dá)式匹配成功。
演示例程中用的是Match,只取一次匹配項(xiàng),事實(shí)上如果用的是Matches,正則表達(dá)式是需要嘗試所有位置的,對于這一組合,同樣道理,在位置3處,由于“\1”沒有字符可供匹配,所以匹配一定是失敗的。
至此,這一組合的匹配完成,有一個成功匹配項(xiàng),匹配結(jié)果為“8”,匹配開始位置為位置2,也就是匹配到的內(nèi)容為第二個“8”。
2.3.2 源字符串二 + 正則表達(dá)式一匹配過程
源字符串二:9878
正則表達(dá)式二:(?<=(\d)\d*)\1
首先在位置0處開始嘗試匹配,由“(?<=(\d)\d*)”取得控制權(quán),長度不固定,至少一位,由位置0處向左查找一位,失敗,“(?<=(\d)\d*)”匹配失敗,導(dǎo)致第一輪匹配嘗試失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置1處嘗試匹配,這一輪的匹配過程與2.3.1節(jié)的組合在位置1處的匹配過程類似,只不過“(\d)\d*”匹配到的是“9”,捕獲組1匹配到的也是“9”,因此“\1”匹配失敗,導(dǎo)致整個表達(dá)式在位置1處匹配失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置2處嘗試匹配,這一輪的匹配過程與2.3.1節(jié)的組合在位置2處的匹配過程類似。首先“(\d)\d*”找到一個成功匹配項(xiàng),匹配到的內(nèi)容是“8”,捕捉組1匹配到的內(nèi)容也是“8”,此時再向左嘗試匹配,又找到一個成功匹配項(xiàng),匹配到的內(nèi)容是“98”,捕捉組1匹配到的內(nèi)容也是“9”,再向左查找時,已無字符,所以“98”就是最長匹配項(xiàng),“(?<=(\d)\d*)”匹配成功,匹配結(jié)果是位置2。由于此時捕獲組1匹配的內(nèi)容是“9”,所以“\1”在位置2處匹配失敗,導(dǎo)致整個表達(dá)式在位置2處匹配失敗。
正則引擎?zhèn)鲃友b置向前傳動,由位置3處嘗試匹配,這一輪的匹配過程與上一輪在位置2處的匹配過程類似。首先“(\d)\d*”找到一個成功匹配項(xiàng)“7”,繼續(xù)向左嘗試,又找到一個成功匹配項(xiàng)“87”,再向左嘗試,又找到一個成功匹配項(xiàng)“987”,此時已為最長匹配,交出控制權(quán),并丟棄所有回溯狀態(tài)。此時捕獲組1匹配的內(nèi)容是“9” 所以“\1”在位置3處匹配失敗,導(dǎo)致整個表達(dá)式在位置3處匹配失敗。
位置4處最終由于“\1”沒有字符可供匹配,所以匹配一定是失敗的。
至此在源字符串所有位置的匹配嘗試都已完成,整個表達(dá)式匹配失敗,未找到成功匹配項(xiàng)。
2.4 小結(jié)
以上匹配過程分析,看似繁復(fù),其實(shí)把握以下幾點(diǎn)就可以了。
1、 逆序環(huán)視中子表達(dá)式為固定長度時,要么匹配成功,要么匹配失敗,沒什么好說的。
2、 逆序環(huán)視中子表達(dá)式為非貪婪模式時,只要找到一個匹配成功項(xiàng),即交出控制權(quán),并丟棄所有可供回溯的狀態(tài)。
3、 逆序環(huán)視中子表達(dá)式為貪婪模式時,只有找到最長匹配成功項(xiàng)時,才會即交出控制權(quán),并丟棄所有可供回溯的狀態(tài)。
也就是說,對于正則表達(dá)式“(?<=SubExp1)SubExp2”,一旦“(?<=SubExp1)”交出控制權(quán),那么它所匹配的位置就已固定,“SubExp1”所匹配的內(nèi)容也已固定,并且沒有可供回溯的狀態(tài)了。
3 逆序環(huán)視匹配原理總結(jié)
再來總結(jié)一下正則表達(dá)式“(?<=SubExp1)SubExp2”的匹配過程吧。逆序環(huán)視的匹配原理圖如下圖所示。
圖3-1 逆序環(huán)視匹配原理圖
正則表達(dá)式“(?<=SubExp1)SubExp2”的匹配過程,可分為主匹配流程和子匹配流程兩個流程,主匹配流程如下圖所示。
圖3-2 主匹配流程圖
主匹配流程:
1、 由位置0處向右嘗試匹配,在找到滿足“(?<=SubExp1)”最小長度要求的位置前,匹配一定是失敗的,直到找到這樣一個的位置x,x滿足“(?<=SubExp1)”最小長度要求;
2、 從位置x處向左查找滿足“SubExp1”最小長度要求的位置y;
3、 由“SubExp1”從位置y開始向右嘗試匹配,此時進(jìn)入一個獨(dú)立的子匹配過程;
4、 如果“SubExp1”在位置y處子匹配還需要下一輪子匹配,則再向左查找一個y’,也就是y-1重新進(jìn)入獨(dú)立的子匹配過程,如此循環(huán),直到不再需要下一輪子匹配,子匹配成功則進(jìn)入步驟5,最終匹配失敗則報(bào)告整個表達(dá)式匹配失?。?br />5、 “(?<=SubExp1)”成功匹配后,控制權(quán)交給后面的子表達(dá)式“SubExp2”,繼續(xù)嘗試匹配,直到整個表達(dá)式匹配成功或失敗,報(bào)告在位置x處整個表達(dá)式匹配成功或失??;
6、 如有必要,繼續(xù)查找下一位置x’,并開始新一輪嘗試匹配。
子匹配流程如下圖所示。
圖3-3 子匹配流程圖
子匹配過程:
1、 進(jìn)入子匹配后,源字符串即已確定,也就是位置y和位置x之間的子字符串,而此時的正則表達(dá)式則變成了“^SubExp1$”,因?yàn)樵谶@一輪子匹配當(dāng)中,一旦匹配成功,則匹配開始位置一定是y,匹配結(jié)束位置一定是x;
2、 子表達(dá)式長度固定時,要么匹配成功,要么匹配失敗,返回匹配結(jié)果,并且不需要下一輪子匹配;
3、 子表達(dá)式長度不固定時,區(qū)分是非貪婪模式還是貪婪模式;
4、 如果是非貪婪模式,匹配失敗,報(bào)告失敗,并且要求進(jìn)行下一輪子匹配;匹配成功,丟棄所有回溯狀態(tài),報(bào)告成功,并且不再需要嘗試下一輪子匹配;
5、 如果是貪婪模式,匹配失敗,報(bào)告失敗,并且要求進(jìn)行下一輪子匹配;匹配成功,丟棄所有回溯狀態(tài),報(bào)告成功,記錄本次匹配成功內(nèi)容,并且要求嘗試下一輪子匹配,直到取得最長匹配為止;
在特定的一輪匹配中,x的位置是固定的,而逆序環(huán)視中的子表達(dá)式“SubExp1”,在報(bào)告最終的匹配結(jié)果前,匹配開始的位置是不可預(yù)知的,需要經(jīng)過一輪以上的子匹配才能確定,但匹配結(jié)束的位置一定是位置x。
當(dāng)然,這只是針對特定的一輪匹配而言的,當(dāng)這輪匹配失敗,正則引擎?zhèn)鲃友b置會向前傳動,使x=x+1,再進(jìn)入下一輪匹配嘗試,直到整個表達(dá)式報(bào)告匹配成功或失敗為止。
至此逆序環(huán)視的匹配原理已基本上分析完了,當(dāng)然,還有更復(fù)雜的,如“SubExp1”中既包含貪婪模式子表達(dá)式,又包含非貪婪模式子表達(dá)式,但無論怎樣復(fù)雜,都是要遵循以上匹配原理的,所以只要理解了以上匹配原理,逆序環(huán)視也就沒什么秘密可言了。
相關(guān)文章
在ASP中用“正則表達(dá)式對象”來校驗(yàn)數(shù)據(jù)的合法性
在ASP中用“正則表達(dá)式對象”來校驗(yàn)數(shù)據(jù)的合法性...2006-06-06正則表達(dá)式基礎(chǔ)學(xué)習(xí)一文入門
這篇文章主要為大家介紹了正則表達(dá)式基礎(chǔ)學(xué)習(xí)一文入門詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03Python中正則表達(dá)式match()、search()函數(shù)及match()和search()的區(qū)別詳解
這篇文章主要介紹了Python中正則表達(dá)式match()、search()函數(shù)及match()和search()的區(qū)別詳解的相關(guān)資料,需要的朋友可以參考下2015-09-09除捕獲組的語法外,其它的(?...)語法都不是捕獲組的驗(yàn)證
這篇文章主要介紹了除捕獲組的語法外,其它的(?...)語法都不是捕獲組的驗(yàn)證,需要的朋友可以參考下2017-04-04利用正則表達(dá)式進(jìn)行中文排版的實(shí)例教程
中文正則表達(dá)式的匹配規(guī)則不像其他正則規(guī)則一樣容易記住,下面這篇文章主要給大家介紹了關(guān)于如何利用正則表達(dá)式進(jìn)行中文排版的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-02-02asp的RegExp對象正則表達(dá)式功能用法[比較全]
RegExp對象提供簡單的正則表達(dá)式支持功能。達(dá)到更好的替換效果。2011-04-04