1. 前言
- 前面的正則的基礎(chǔ)語(yǔ)法了解之后,正式開(kāi)始實(shí)際應(yīng)用
- 對(duì)基礎(chǔ)知識(shí)感興趣的可以看看我寫(xiě)的基礎(chǔ)篇 《正則表達(dá)不再control+v》
-
結(jié)尾有一些常用的正則表達(dá)式,但是想了解為什么還是最好順序閱讀
awesome.JPG
2.子表達(dá)式
2.1 概念
-
(
和)
括起來(lái)的就是子表達(dá)式 - 我的理解:子表達(dá)式的目的是為了增加匹配的優(yōu)先級(jí),子表達(dá)式內(nèi)的優(yōu)先級(jí)較高,優(yōu)先匹配
- 子表達(dá)式可以嵌套,這個(gè)在下面會(huì)通過(guò)例子來(lái)解釋
2.2 實(shí)戰(zhàn)-IP地址的匹配
我們會(huì)一步一步完善和簡(jiǎn)化一個(gè)IP的正則表達(dá)式
-
需求分析:IP 地址是由
.
分隔的四組數(shù)字,如192.168.1.106。因?yàn)槊總€(gè)部分的數(shù)字都可以為1-3位數(shù)字字符
IP地址匹配1.0.png -
分析
first:
\d{1,3}
表示匹配一個(gè)由數(shù)字組成的1-3位的字符串
second:\d{1,3}\.
表示1-3位數(shù)字,并以.
結(jié)尾
third:最后一組字符串不需要以.
結(jié)尾,所以\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
貌似可以解決IP的匹配 -
但是d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}這個(gè)正則,重復(fù)表達(dá)式太多,垃圾代碼那么多能忍么???那么子表達(dá)式就出現(xiàn)用處了
IP地址匹配1.0-子表達(dá)式簡(jiǎn)化版.png -
分析
\d{1,3}\.
以()
子表達(dá)式括起來(lái),并加上重復(fù)執(zhí)行次數(shù),能簡(jiǎn)化正則的可閱讀性 -
那么我們的IP正則的容錯(cuò)性到底怎么樣?
IP地址匹配-非法IP校驗(yàn).png 非法IP也能被匹配,說(shuō)明我們的IP匹配有問(wèn)題,其實(shí)是需求分析有問(wèn)題,IP的地址規(guī)則并未完全體現(xiàn),那么補(bǔ)充需求之后再完善我們的IP地址匹配吧
IP地址規(guī)則:
- 所有的一位數(shù)和兩位數(shù)
- 三位數(shù)的第一位為 1
- 如果三位數(shù)的第一位為 2 ,且第二位從 0 到 4
- 如果三位數(shù)的前二位為 25 ,且第三位從 0 到 5
- 總結(jié):0-255.0-255.0-255.0-255 就是我們要寫(xiě)的
-
明確了規(guī)則,把每條規(guī)則實(shí)現(xiàn)即可
IP地址匹配2.0.png - 新的實(shí)現(xiàn)
(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))
,一個(gè)匹配里嵌套了四組子表達(dá)式
解析:
1.將整個(gè)正則拆成兩個(gè)部分((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}
和((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))
,前一部分重復(fù)三次用來(lái)表示前面三組數(shù)字,并且以.
結(jié)尾,后一部分表示最后一組IP地址
2.第一部分:(\d{1,2})
,這個(gè)子表達(dá)式將匹配一位或者兩位任意數(shù)字
3.第二部分:((1\d{2})
,這個(gè)子表達(dá)式將匹配以1開(kāi)頭的后兩位任意數(shù)字的三位數(shù)字
4.第三部分:(2[0-4]\d)
,這個(gè)子表達(dá)式將匹配以2開(kāi)頭的中間一位為0-4,第三位為任意數(shù)字的字符串
5.第四部分:(25[0-5])
,這個(gè)子表達(dá)式將匹配以25開(kāi)頭的尾數(shù)為0-5的三位數(shù)字
- 還有網(wǎng)上很多別的寫(xiě)法,但是我覺(jué)得這個(gè)寫(xiě)法是比較好理解的版本,所以如果有更好的,可以告訴我,畢竟我覺(jué)得真的很長(zhǎng)
2.3 年份匹配
- 這個(gè)需求很簡(jiǎn)單,就是匹配19xx-20xx所有年份
- 目的:體驗(yàn)子表達(dá)式的優(yōu)先級(jí)
- 實(shí)用性:我覺(jué)得這種簡(jiǎn)單的正則在開(kāi)發(fā)中實(shí)用性很強(qiáng),很多都可以用到
年份匹配-錯(cuò)誤版本.png - 解釋
1.
19|20\d{2}
這個(gè)表達(dá)式?jīng)]有達(dá)到我們的效果
2.這個(gè)表達(dá)式其實(shí)的效果是匹配19(兩位)和以20開(kāi)頭的四位數(shù)字
3.這里就能體現(xiàn)子表達(dá)式的效果,我們想要的是19或者20開(kāi)頭的四位數(shù)字,那么我們完全可以這部分用子表達(dá)式括起來(lái),來(lái)實(shí)現(xiàn)效果
2.4 HTML標(biāo)簽匹配
- 需求:匹配H5標(biāo)簽,因?yàn)镠5標(biāo)簽的格式還是很固定的
<xxx>xxx</xxx>
- 知識(shí)點(diǎn):這里會(huì)用到向后引用這個(gè)寫(xiě)法
-
以匹配H標(biāo)簽為例
標(biāo)簽匹配-錯(cuò)誤版.png - 這里就有個(gè)需求就是前面和后面的相同匹配規(guī)則匹配保持一致,比如前面匹配了H2標(biāo)簽,后面還是要匹配H2標(biāo)簽,前后一致
2.4.1 后向引用
- 后向引用就是引用前面的子表達(dá)式
- 使用小括號(hào)指定一個(gè)子表達(dá)式后,匹配這個(gè)子表達(dá)式的文本(也就是此分組捕獲的內(nèi)容)可以在表達(dá)式或其他程序中作進(jìn)一步處理。默認(rèn)情況下,每個(gè)分組會(huì)自動(dòng)擁有一個(gè)組號(hào),規(guī)則是:從左向右,以分組的左括號(hào)為標(biāo)志,第一個(gè)出現(xiàn)的分組的組號(hào)為1,第二個(gè)為2,以此類(lèi)推
- 后向引用用于重復(fù)搜索前面某個(gè)分組匹配的文本
- 可以參考文章: 正則表達(dá)式后向引用~~~~~~ & 正則表達(dá)式后向引用
2.4.2 HTML標(biāo)簽匹配之向后引用
-
但是我這里遇到了個(gè)問(wèn)題:使用Regextor出現(xiàn)了不能匹配正確的向后引用,我不確定是APP不能識(shí)別這種語(yǔ)法還是什么原因,如果有知道請(qǐng)告訴我
Regextor不支持向后引用么?.png -
我們?cè)趚code中使用了匹配查詢(xún),這個(gè)正則完全能達(dá)到我們的要求
xcode匹配結(jié)果.png -
<[hH]([1-5])>.*?</[hH]\1>
分析
<[hH]([1-5])>
中將第一個(gè)子表達(dá)式使用()
括起來(lái),在緩存中使用這個(gè)子表達(dá)式默認(rèn)為第一個(gè)分組
</[hH]\1>
中\1
使用第一個(gè)的子表達(dá)式的匹配取值應(yīng)用到第二處,不如前面匹配了1,后面只能匹配1
3,實(shí)際開(kāi)發(fā)應(yīng)用
- 這里我介紹我常用的應(yīng)用場(chǎng)景,也可以去看小松哥的文章
系統(tǒng)地學(xué)習(xí)正則表達(dá)式(二):進(jìn)階
3.1 查找替換文本
-
2.4.2 HTML標(biāo)簽的匹配中就用xcode的查找操作
xcode匹配.png
3.2 校驗(yàn)字符串是否符合規(guī)則-NSPredicate
- 最常用的一種方式
NSString *string = @"hotCat";
//正則
NSString *regex = @"^ho[a-zA-Z]{2,}*$";
//創(chuàng)建NSPredicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
BOOL result = [predicate evaluateWithObject:string];
3.3 字符串某一個(gè)字符或者字符集的定位
- 用處:特定的字符串的替換,或者某些字符的刪除,都可以使用,因?yàn)榭梢阅玫?strong>想要的NSRange
NSString *string = @"hotCat123";
//使用正則\d+去string中進(jìn)行匹配,得到的時(shí)匹配到的range,在這里為{4,3}。
NSRange range = [string rangeOfString:@"\\d+" options:NSRegularExpressionSearch];
//如果匹配到就打印匹配到的子字符串,在這里為123。
if (range.location != NSNotFound)
{
NSLog(@"%@",[string substringWithRange:range]);
}
分析:
1.\d
+用來(lái)查找數(shù)字
2.rangeOfString:options:會(huì)返回一個(gè)NSRange
,用來(lái)接收匹配的范圍options必須要用NSRegularExpressionSearch,代表用正則去匹配
3.當(dāng)寫(xiě)正則字符串時(shí),\需要寫(xiě)成\\ ,所以,\d+需要寫(xiě)成\\d+
3.4 NSRegularExpression
- NSRegularExpression這個(gè)類(lèi)可以用戶(hù)來(lái)查找字符串中符合要求的第一個(gè)匹配結(jié)果或者所有匹配結(jié)果
- 這個(gè)使用很簡(jiǎn)單,就不詳細(xì)介紹了,如果有想知道使用的,可以移步oc中正則表達(dá)式NSRegularExpression類(lèi)詳解
3.5 其它
- 我覺(jué)得還可以有很多高級(jí)的用處,但是實(shí)際開(kāi)發(fā)中還沒(méi)遇到,如果有遇到可以告訴我,我會(huì)去在深入學(xué)習(xí)下,謝謝啦!!!
4. 最后的福利
- 最后的留一些常用的校驗(yàn)吧,以免有人偷懶,所以寫(xiě)在最后,但是可能不知道是否符合最新的標(biāo)準(zhǔn),比如手機(jī)號(hào)碼,新字段開(kāi)發(fā)太快了
/**
* 手機(jī)號(hào)碼:
* 13[0-9], 14[5,7], 15[0, 1, 2, 3, 5, 6, 7, 8, 9], 17[0, 1, 6, 7, 8], 18[0-9]
* 移動(dòng)號(hào)段: 134,135,136,137,138,139,147,150,151,152,157,158,159,170,178,182,183,184,187,188
* 聯(lián)通號(hào)段: 130,131,132,145,155,156,170,171,175,176,185,186
* 電信號(hào)段: 133,149,153,170,173,177,180,181,189
*/
NSString *MOBILE = @"^1(3[0-9]|4[57]|5[0-35-9]|7[0135678]|8[0-9])\\d{8}$";
/**
* 中國(guó)移動(dòng):China Mobile
* 134,135,136,137,138,139,147,150,151,152,157,158,159,170,178,182,183,184,187,188
*/
NSString *CM = @"^1(3[4-9]|4[7]|5[0-27-9]|7[08]|8[2-478])\\d{8}$";
/**
* 中國(guó)聯(lián)通:China Unicom
* 130,131,132,145,155,156,170,171,175,176,185,186
*/
NSString *CU = @"^1(3[0-2]|4[5]|5[56]|7[0156]|8[56])\\d{8}$";
/**
* 中國(guó)電信:China Telecom
* 133,149,153,170,173,177,180,181,189
*/
NSString *CT = @"^1(3[3]|4[9]|53|7[037]|8[019])\\d{8}$";
郵箱: ^[a-zA-Z0-9]{4,}@[a-z0-9A-Z]{2,}\\.[a-zA-Z]{2,}$
大陸固定電話(huà)號(hào)碼: ^\\d{4}-|\\d{3}-)?(\\d{8}|\\d{7}$
身份證號(hào): \\d{14}[[0-9],0-9xX]
Email地址: ^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\.\\w+([-.]\\w+)*$
純數(shù)字: ^[0-9]*$
由數(shù)字和英文字母組成: ^[A-Za-z0-9]+$
QQ號(hào): ^[1-9][0-9]\{4,\}$
中國(guó)郵政編碼: ^[1-9]\\d{5}(?!\\d)$
URL: ^http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?$
純漢字中文:^[\u4e00-\u9fa5]{0,}$