国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > JS > 正文

javascript 正則表達式分組、斷言詳解

2024-05-06 16:36:38
字體:
來源:轉載
供稿:網友

 javascript 正則表達式分組、斷言詳解

  提示:閱讀本文需要有一定的正則表達式基礎。

       正則表達式中的斷言,作為高級應用出現,倒不是因為它有多難,而是概念比較抽象,不容易理解而已,今天就讓小菜通俗的講解一下。

       如果不用斷言,以往用過的那些表達式,僅僅能獲取到有規律的字符串,而不能獲取無規律的字符串。

       舉個例子,比如html源碼中有<title>xxx</title>標簽,用以前的知識,我們只能確定源碼中的<title>和</title>是固定不變的。因此,如果想獲取頁面標題(xxx),充其量只能寫一個類似于這樣的表達式:<title>.*</title>,而這樣寫匹配出來的是完整的<title>xxx</title>標簽,并不是單純的頁面標題xxx。

       想解決以上問題,就要用到斷言知識。

       在講斷言之前,讀者應該先了解分組,這有助于理解斷言。

       分組在正則中用()表示,根據小菜理解,分組的作用有兩個:

       n  將某些規律看成是一組,然后進行組級別的重復,可以得到意想不到的效果。

       n  分組之后,可以通過后向引用簡化表達式。

        先來看第一個作用,對于IP地址的匹配,簡單的可以寫為如下形式:

       /d{1,3}./d{1,3}./d{1,3}./d{1,3}

       但仔細觀察,我們可以發現一定的規律,可以把./d{1,3}看成一個整體,也就是把他們看成一組,再把這個組重復3次即可。表達式如下:

       /d{1,3}(./d{1,3}){3}

       這樣一看,就比較簡潔了。

再來看第二個作用,就拿匹配<title>xxx</title>標簽來說,簡單的正則可以這樣寫:

       <title>.*</title>

       可以看出,上邊表達式中有兩個title,完全一樣,其實可以通過分組簡寫。表達式如下:

       <(title)>.*<//1>

       這個例子實際上就是反向引用的實際應用。對于分組而言,整個表達式永遠算作第0組,在本例中,第0組是<(title)>.*<//1>,然后從左到右,依次為分組編號,因此,(title)是第1組。

       用/1這種語法,可以引用某組的文本內容,/1當然就是引用第1組的文本內容了,這樣一來,就可以簡化正則表達式,只寫一次title,把它放在組里,然后在后邊引用即可。

       以此為啟發,我們可不可以簡化剛剛的IP地址正則表達式呢?原來的表達式為/d{1,3}(./d{1,3}){3},里邊的/d{1,3}重復了兩次,如果利用后向引用簡化,表達式如下:

       (/d{1,3})(./1){3}

       簡單的解釋下,把/d{1,3}放在一組里,表示為(/d{1,3}),它是第1組,(./1)是第2組,在第2組里通過/1語法,后向引用了第1組的文本內容。

       經過實際測試,會發現這樣寫是錯誤的,為什么呢?

       小菜一直在強調,后向引用,引用的僅僅是文本內容,而不是正則表達式!

       也就是說,組中的內容一旦匹配成功,后向引用,引用的就是匹配成功后的內容,引用的是結果,而不是表達式。

       因此,(/d{1,3})(./1){3}這個表達式實際上匹配的是四個數都相同的IP地址,比如:123.123.123.123。

       至此,讀者已經掌握了傳說中的后向引用,就這么簡單。

       接下來說說什么是斷言。

       所謂斷言,就是指明某個字符串前邊或者后邊,將會出現滿足某種規律的字符串。

       就拿文章開篇的例子來說,我們想要的是xxx,它沒有規律,但是它前邊肯定會有<title>,后邊肯定會有</title>,這就足夠了。

       想指定xxx前肯定會出現<title>,就用正后發斷言,表達式:(?<=<title>).*

       向指定xxx后邊肯定會出現</title>,就用正先行斷言,表達式:.*(?=</title>)

       兩個加在一起,就是(?<=<title>).*(?=</title>)

       這樣就能匹配到xxx。

     

       相信讀者看到這,已經蒙了,不用急,待小菜慢慢講來。

     

       其實掌握了規律,就很簡單了,無論是先行還是后發,都是相對于xxx而言的,也就是相對于目標字符串而言。

       假如目標字符串后邊有條件,可以理解為目標字符串在前,就用先行斷言,放在目標字符串之后。

       假如目標字符串前邊有條件,可以理解為目標字符串在后,就用后發斷言,放在目標字符串之前。

       假如指定滿足某個條件,就是正。

       假如指定不滿足某個條件,就是負。

       斷言只是條件,幫你找到真正需要的字符串,本身并不會匹配!

 

(?=X )

零寬度正先行斷言。僅當子表達式 X 在 此位置的右側匹配時才繼續匹配。例如,/w+(?=/d) 與后跟數字的單詞匹配,而不與該數字匹配。此構造不會回溯。

(?!X)

零寬度負先行斷言。僅當子表達式 X 不在 此位置的右側匹配時才繼續匹配。例如,例如,/w+(?!/d) 與后不跟數字的單詞匹配,而不與該數字匹配 。

(?<=X)

零寬度正后發斷言。僅當子表達式 X 在 此位置的左側匹配時才繼續匹配。例如,(?<=19)99 與跟在 19 后面的 99 的實例匹配。此構造不會回溯。

(?<!X)

零寬度負后發斷言。僅當子表達式 X 不在此位置的左側匹配時才繼續匹配。例如,(?<!19)99 與不跟在 19 后面的 99 的實例匹配

 

       從斷言的表達形式可以看出,它用的就是分組符號,只不過開頭都加了一個問號,這個問號就是在說這是一個非捕獲組,這個組沒有編號,不能用來后向引用,只能當做斷言。

       教程到此結束,希望大家閱讀愉快!


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 陆川县| 治多县| 大足县| 奉化市| 桑日县| 达州市| 永宁县| 迭部县| 惠东县| 万盛区| 贵州省| 济阳县| 夏津县| 长兴县| 齐河县| 华宁县| 大荔县| 新兴县| 潢川县| 泗水县| 潍坊市| 河津市| 岢岚县| 梁河县| 信宜市| 沧州市| 孟州市| 宜君县| 遵义市| 陕西省| 曲水县| 柳江县| 渑池县| 安丘市| 宝清县| 阜城县| 兴山县| 封开县| 琼海市| 深水埗区| 旬邑县|