摘要:負(fù)向先行斷言負(fù)前瞻語(yǔ)法作用匹配非表達(dá)式的前面內(nèi)容,不返回本身。我們來(lái)測(cè)試一下輸出結(jié)果嗯,這就是我們想要的了。
由于上一篇文章:《正則表達(dá)式真的很騷,可惜你不會(huì)寫(xiě)!??!》 發(fā)表之后,不少網(wǎng)友說(shuō)怎么沒(méi)講斷言沒(méi)講反向沒(méi)講貪婪....,甚至有老鐵說(shuō)我褲子都脫了你就給講了一點(diǎn),哈哈哈,好吧,趁著山竹臺(tái)風(fēng)被迫放假在家的時(shí)間,把正則剩余的一些知識(shí)點(diǎn)給講一下,希望大家喜歡,希望這次脫褲子閱讀的老鐵可以暢快的操作了。
本文旨在用最通俗的語(yǔ)言講述最枯燥的基本知識(shí)。
1. 零寬斷言文章提綱:
零寬斷言
捕獲和非捕獲
反向引用
貪婪和非貪婪
反義
無(wú)論是零寬還是斷言,聽(tīng)起來(lái)都古古怪怪的,
那先解釋一下這兩個(gè)詞。
斷言:俗話(huà)的斷言就是“我斷定什么什么”,而正則中的斷言,就是說(shuō)正則可以指明在指定的內(nèi)容的前面或后面會(huì)出現(xiàn)滿(mǎn)足指定規(guī)則的內(nèi)容,意思正則也可以像人類(lèi)那樣斷定什么什么,比如"ss1aa2bb3",正則可以用斷言找出aa2前面有bb3,也可以找出aa2后面有ss1.
零寬:就是沒(méi)有寬度,在正則中,斷言只是匹配位置,不占字符,也就是說(shuō),匹配結(jié)果里是不會(huì)返回?cái)嘌员旧怼?/p>
意思是講明白了,那他有什么用呢?
我們來(lái)舉個(gè)栗子:
假設(shè)我們要用爬蟲(chóng)抓取csdn里的文章閱讀量。通過(guò)查看源代碼可以看到文章閱讀量這個(gè)內(nèi)容是這樣的結(jié)構(gòu)
"閱讀數(shù):641"
其中只有‘641’這個(gè)是一個(gè)變量,也就是不同文章有不同的值,當(dāng)我們拿到這個(gè)字符串時(shí),需要獲得這里邊的‘641’有很多種辦法,但如果使用正則應(yīng)該怎么匹配呢?
下面先講一下幾種類(lèi)型的斷言:
正向先行斷言(正前瞻):
語(yǔ)法:(?=pattern)
作用:匹配pattern表達(dá)式的前面內(nèi)容,不返回本身。
這樣子說(shuō),還是一臉懵逼,好吧,回歸剛才那個(gè)栗子,要取到閱讀量,在正則表達(dá)式中就意味著要能匹配到‘’前面的數(shù)字內(nèi)容
按照上所說(shuō)的正向先行斷言可以匹配表達(dá)式前面的內(nèi)容,那意思就是:(?=) 就可以匹配到前面的內(nèi)容了。
匹配什么內(nèi)容呢?如果要所有內(nèi)容那就是:
String reg=".+(?=)"; String test = "閱讀數(shù):641"; Pattern pattern = Pattern.compile(reg); Matcher mc= pattern.matcher(test); while(mc.find()){ System.out.println("匹配結(jié)果:") System.out.println(mc.group()); } //匹配結(jié)果: //閱讀數(shù):641
可是老哥我們要的只是前面的數(shù)字呀,那也簡(jiǎn)單咯,匹配數(shù)字 d,那可以改成:
String reg="d+(?=)";
String test = "閱讀數(shù):641";
Pattern pattern = Pattern.compile(reg);
Matcher mc= pattern.matcher(test);
while(mc.find()){
System.out.println(mc.group());
}
//匹配結(jié)果:
//641
大功告成!
正向后行斷言(正后顧):
語(yǔ)法:(?<=pattern)
作用:匹配pattern表達(dá)式的后面的內(nèi)容,不返回本身。
有先行就有后行,先行是匹配前面的內(nèi)容,那后行就是匹配后面的內(nèi)容啦。
上面的栗子,我們也可以用后行斷言來(lái)處理.
//(?<=閱讀數(shù):)d+
String reg="(?<=閱讀數(shù):)d+";
String test = "閱讀數(shù):641";
Pattern pattern = Pattern.compile(reg);
Matcher mc= pattern.matcher(test);
while(mc.find()){
System.out.println(mc.group());
}
//匹配結(jié)果:
//641
就這么簡(jiǎn)單。
負(fù)向先行斷言(負(fù)前瞻)
語(yǔ)法:(?!pattern)
作用:匹配非pattern表達(dá)式的前面內(nèi)容,不返回本身。
有正向也有負(fù)向,負(fù)向在這里其實(shí)就是非的意思。
舉個(gè)栗子:比如有一句 “我愛(ài)祖國(guó),我是祖國(guó)的花朵”
現(xiàn)在要找到不是"的花朵"前面的祖國(guó)
用正則就可以這樣寫(xiě):
祖國(guó)(?!的花朵)
負(fù)向后行斷言(負(fù)后顧)
語(yǔ)法:(?
作用:匹配非pattern表達(dá)式的后面內(nèi)容,不返回本身。
2. 捕獲和非捕獲單純說(shuō)到捕獲,他的意思是匹配表達(dá)式,但捕獲通常和分組聯(lián)系在一起,也就是“捕獲組”
捕獲組:匹配子表達(dá)式的內(nèi)容,把匹配結(jié)果保存到內(nèi)存中中數(shù)字編號(hào)或顯示命名的組里,以深度優(yōu)先進(jìn)行編號(hào),之后可以通過(guò)序號(hào)或名稱(chēng)來(lái)使用這些匹配結(jié)果。
而根據(jù)命名方式的不同,又可以分為兩種組:
數(shù)字編號(hào)捕獲組:
語(yǔ)法:(exp)
解釋?zhuān)簭谋磉_(dá)式左側(cè)開(kāi)始,每出現(xiàn)一個(gè)左括號(hào)和它對(duì)應(yīng)的右括號(hào)之間的內(nèi)容為一個(gè)分組,在分組中,第0組為整個(gè)表達(dá)式,第一組開(kāi)始為分組。
比如固定電話(huà)的:020-85653333
他的正則表達(dá)式為:(0d{2})-(d{8})
按照左括號(hào)的順序,這個(gè)表達(dá)式有如下分組:
序號(hào) | 編號(hào) | 分組 | 內(nèi)容 |
---|---|---|---|
0 | 0 | (0d{2})-(d{8}) | 020-85653333 |
1 | 1 | (0d{2}) | 020 |
2 | 2 | (d{8}) | 85653333 |
我們用Java來(lái)驗(yàn)證一下:
String test = "020-85653333"; String reg="(0d{2})-(d{8})"; Pattern pattern = Pattern.compile(reg); Matcher mc= pattern.matcher(test); if(mc.find()){ System.out.println("分組的個(gè)數(shù)有:"+mc.groupCount()); for(int i=0;i<=mc.groupCount();i++){ System.out.println("第"+i+"個(gè)分組為:"+mc.group(i)); } }
輸出結(jié)果:
分組的個(gè)數(shù)有:2 第0個(gè)分組為:020-85653333 第1個(gè)分組為:020 第2個(gè)分組為:85653333
可見(jiàn),分組個(gè)數(shù)是2,但是因?yàn)榈?個(gè)為整個(gè)表達(dá)式本身,因此也一起輸出了。
命名編號(hào)捕獲組:
語(yǔ)法:(?
exp)
解釋?zhuān)悍纸M的命名由表達(dá)式中的name指定
比如區(qū)號(hào)也可以這樣寫(xiě):(?0d{2})-(? d{8})
按照左括號(hào)的順序,這個(gè)表達(dá)式有如下分組:
序號(hào) | 名稱(chēng) | 分組 | 內(nèi)容 |
---|---|---|---|
0 | 0 | (0d{2})-(d{8}) | 020-85653333 |
1 | quhao | (0d{2}) | 020 |
2 | haoma | (d{8}) | 85653333 |
用代碼來(lái)驗(yàn)證一下:
String test = "020-85653333"; String reg="(?0d{2})-(? d{8})"; Pattern pattern = Pattern.compile(reg); Matcher mc= pattern.matcher(test); if(mc.find()){ System.out.println("分組的個(gè)數(shù)有:"+mc.groupCount()); System.out.println(mc.group("quhao")); System.out.println(mc.group("haoma")); }
輸出結(jié)果:
分組的個(gè)數(shù)有:2 分組名稱(chēng)為:quhao,匹配內(nèi)容為:020 分組名稱(chēng)為:haoma,匹配內(nèi)容為:85653333
非捕獲組:
語(yǔ)法:(?:exp)
解釋?zhuān)汉筒东@組剛好相反,它用來(lái)標(biāo)識(shí)那些不需要捕獲的分組,說(shuō)的通俗一點(diǎn),就是你可以根據(jù)需要去保存你的分組。
比如上面的正則表達(dá)式,程序不需要用到第一個(gè)分組,那就可以這樣寫(xiě):
(?: