iOS中使用正則表達式就不得不提NSRegularExpression,所以我們需要先搞清楚什么是NSRegularExpression,養成好習慣先查看下文檔:NSRegularExpression文檔,看到文檔中的第一段:
# 原文:
The NSRegularExpression class is used to represent and apply regular expressions to Unicode strings. An instance of this class is an immutable representation of a compiled regular expression pattern and various option flags. The pattern syntax currently supported is that specified by ICU. The ICU regular expressions are described athttp://userguide.icu-project.org/strings/regexp.
大概翻譯(翻譯可能不太準,但是意思大概就是這樣。建議大家看原文。):
NSRegularExpression是用Unicode字符串表達和應用正則表達式的類。這個類的實例是代表一個不可變的正則表達式和選項標識。當前支持的語法是ICU。ICU正則表達式的具體說明在:http://userguide.icu-project.org/strings/regexp
第一段話給了我們4個信息:
1) NSRegularExpression支持的是Unicode字符,代表可以輸入所有字符。
2) NSRegularExpression實例的表達式內容和選項標識是不能改變的。直接查看NSRegularExpression的.h文件:
```
@interface NSRegularExpression:NSObject ()
@property(readonly,copy)NSString*pattern;
@property(readonly)NSRegularExpressionOptionsoptions;
+ (nullableNSRegularExpression*)regularExpressionWithPattern:(NSString*)pattern options:(NSRegularExpressionOptions)options error:(NSError**)error;
- (nullable instancetype)initWithPattern:(NSString*)pattern options:(NSRegularExpressionOptions)options error:(NSError**)errorNS_DESIGNATED_INITIALIZER;
@end
```
從.h文件中可以看出,屬性pattern和options是用readonly修飾的代表著只讀不可賦值,在初始化的時候可以賦值。
3) NSRegularExpression支持的ICU正則表達式語法。
4.)ICU正則表達式的詳解地址:http://userguide.icu-project.org/strings/regexp(這個被墻了,需要翻墻。)
ICU正則表達式是基于Perl正則表達式的,而Perl正則表達式則是基于Version 8 Regular Expressions,有興趣的可以自行查閱:ICU Regular Expressions,Perl Regular Expressions,Version 8 Regular Expressions,在這里就不祥說了。
Flag Options
先看到文檔中的Flag Options,標識選項。如下表:
Flag Options描述
i不區分大小寫
x允許空格和注釋
s.匹配行終止符,默認情況下是不匹配的
m^和$匹配每一行的開頭和結尾,默認情況下是只匹配文本開頭和結尾。
Para如果設置了,字的邊界按照Unicode UAX 29中的文本邊界發現單詞的定義。默認情況下,字邊界由字符的簡單分類為“word”或“non-word”,這近似于傳統正則表達式行為的手段鑒定。用兩個選擇獲得的結果可以是在空間和其他非單詞字符的運行完全不同。
我們再來看看NSRegularExpressionOptions:
typedefNS_OPTIONS(NSUInteger, NSRegularExpressionOptions){? NSRegularExpressionCaseInsensitive? ? ? ? ? ? =1<<0,/* Match letters in the pattern independent of case. */NSRegularExpressionAllowCommentsAndWhitespace? =1<<1,/* Ignore whitespace and #-prefixed comments in the pattern. */NSRegularExpressionIgnoreMetacharacters? ? ? ? =1<<2,/* Treat the entire pattern as a literal string. */NSRegularExpressionDotMatchesLineSeparators? ? =1<<3,/* Allow . to match any character, including line separators. */NSRegularExpressionAnchorsMatchLines? ? ? ? ? =1<<4,/* Allow ^ and $ to match the start and end of lines. */NSRegularExpressionUseUnixLineSeparators? ? ? =1<<5,/* Treat only \n as a line separator (otherwise, all standard line separators are used). */NSRegularExpressionUseUnicodeWordBoundaries? ? =1<<6/* Use Unicode TR#29 to specify word boundaries (otherwise, traditional regular expression word boundaries are used). */};
其實上面的注釋已經說的很清楚了。
typedefNS_OPTIONS(NSUInteger, NSRegularExpressionOptions){? NSRegularExpressionCaseInsensitive? ? ? ? ? ? =1<<0,/* 匹配是不區分大小寫 */NSRegularExpressionAllowCommentsAndWhitespace? =1<<1,/* 忽略空白和注釋 */NSRegularExpressionIgnoreMetacharacters? ? ? ? =1<<2,/* 將所有的patter當作普通字符串,例如:$\[]()+*^.|*/NSRegularExpressionDotMatchesLineSeparators? ? =1<<3,/* .匹配換行和空格 */NSRegularExpressionAnchorsMatchLines? ? ? ? ? =1<<4,/* $,^匹配每一行的開頭和結尾 */NSRegularExpressionUseUnixLineSeparators? ? ? =1<<5,/* 行分隔符只有\n(否則,所有標準的行分隔符時,例如\r也是換行) */NSRegularExpressionUseUnicodeWordBoundaries? ? =1<<6/* 使用 Unicode TR#29 規定的邊界。(否則,使用傳統的正則表達式的詞邊界) */};
Regular Expression Metacharacters(正則表達式元字符)
元字符表如下:
字符表達式描述
\a匹配Bell(響鈴),\u0007,ASCII表第七位
\A匹配文本開頭,和^不同的是不能匹配換行的開頭。^在NSRegularExpressionAnchorsMatchLines條件下可以匹配每一行的開頭,同樣$也是一樣
\b匹配詞的前面后面,或者后面,例如:匹配字符串為這是一個test代碼.,正則為t\b或者\bt,前者匹配t結尾,后者匹配t開頭,你可以理解為\b表示邊界。分隔符可以是特殊字符或者中文。
\B文檔原話是這樣的:Match if the current position is not a word boundary.,意思應該是:如果當前位置不是邊界則匹配。很容易讓人理解為\B修飾的字符串不在邊界,然而實際情況并不是這樣。可以把\B理解為非邊界,例如待匹配字符串有:test、tes、est,我們需要匹配的es在不在頭部也不再尾部的字符串,相對應的正則應該是:\Bes\B,如果正則是\Bes則會匹配到:test和tes,正則是es\B則會匹配到:test和est
\cX匹配控制字符,例如\cM匹配control-M或者回車,點擊查看更多的控制字符
\d匹配10進制數,0~9
\D匹配非10進制數
\E配合\Q使用,\Q開頭\E結尾,中間的字符串都會被當作普通字符串。例如:\Q$\E等價于\$
\e匹配空格, \u001B
\f匹配\u000F
\n匹配\u000A
\G連續匹配,從當前位置開始匹配一直匹配到第一個不匹配的地方結束,例如待匹配字符串test1test,正則[a-z]可以匹配8個字符,如果正則是\Gtest則能匹配4個,如果待匹配字符串為:1test1test,正則:\Gtest將匹配不到任何字符串,正則:1\Gtest能匹配到4個字符
\N{UNICODE CHARACTER NAME}Match the named character.(具體作用和使用方式不明。。。。)
\p{UNICODE PROPERTY NAME}匹配指定的UNICODE屬性名的字符,例如:屬性名:Lu代表的是大寫字母,待匹配字符串:Test,正則:\p{Lu},匹配結果是T。更多屬性名
\P{UNICODE PROPERTY NAME}匹配非指定UNICODE屬性名的字符,例如:屬性名:Lu代表的是大寫字母,待匹配字符串:Test,正則:\P{Lu},匹配結果是e,s,t。更多屬性名
\Q配合\E使用,\Q開頭\E結尾,中間的字符串都會被當作普通字符串。例如:\Q$\E等價于\$
\r換號符,\u000D.
\t制表符, \u0009
\s空白字符串,[\t\n\f\r\p{Z}]
\S非空白字符串, [^\t\n\f\r\p{Z}]
\uhhhh16進制直為hhhh的字符串
\uhhhhhhhh16進制直為hhhhhhhh的字符串
\w非字符
\W字符
\x{hhhh}16進制值為hhhh的字符
\xhh16進制值為hh的字符
\X官方文檔解釋:Match a Grapheme Cluster.
\Z結束輸入,文檔原文:Match if the current position is at the end of input, but before the final line terminator, if one exists.。
\z結束輸入,文檔原文:Match if the current position is at the end of input.
\n換行符,\u000A
\0ooo8進制值為ooo的字符串
[pattern]pattern表示要匹配的字符串,例如[A]表示匹配A
.任意字符
^開頭
$結尾
\轉義,例如匹配$,正則:\$
上表是筆者對文檔中的元字符理解,有幾個筆者也不清楚例如:\N{UNICODE CHARACTER NAME}怎么使用和具備什么作用。
正則表達式操作符
操作符表:
操作符描述
丨丨或,例如A丨B,匹配A或B
*0次或者多次
+1次或者多次
?0次或1次
{n}n為數字,表示前面匹配連續出現n次,例如:3{2}表示33
{n,}n為數字,表示前面匹配至少連續出現n次,例如:3{2,},表示:33,333,3333...}
{n,m}n,m為數字,n<=m,表示前面匹配連續出現n~m次,例如:3{2,5},表示:33,333,3333,33333
*?0次或者多次,但是次數盡可能少,例如正則:[\d]*?,待匹配字符:12345,匹配次數6次,都是空
+?1次或者多次,但是次數盡可能少,例如正則:[\d]+?,待匹配字符:12345,匹配次數5次,匹配結果是:1,2,3,4,5。
??0次或1次,例如正則:[\d]??,待匹配字符:12345,匹配次數6次,都是空
{n}?同{n}
{n,}?n為數字,但是次數盡可能少。例如正則:[\d]{1,}?,待匹配字符:12345,匹配次數5次,匹配結果是:1,2,3,4,5。
{n,m}?同{n,m},但是次數盡可能少。例如正則:[\d]{1,5}?,待匹配字符:12345,匹配次數5次,匹配結果是:1,2,3,4,5。
*+0次或者多次,但是次數盡可能多(貪婪模式)。例如正則:[\d]*+,待匹配字符:12345,匹配次數2次,匹配結果是:12345和空。
++1次或者多次,但是次數盡可能多(貪婪模式)。例如正則:[\d]*+,待匹配字符:12345,匹配次數1次,匹配結果是:12345。
?+0次或1次,但是次數盡可能多(貪婪模式)。例如正則:[\d]*+,待匹配字符:12345,匹配次數5次,匹配結果是:1,2,3,4,5。
{n}+同{n}
{n,}+同{n,},但是次數盡可能多(貪婪模式)。例如正則:[\d]{1,}+,待匹配字符:12345,匹配次數1次,匹配結果是:12345。
{n,m}+同{n,m},但是次數盡可能多(貪婪模式)。例如正則:[\d]{1,5}+,待匹配字符:12345,匹配次數1次,匹配結果是:12345。
(...)子表達式,并捕獲匹配字符(捕獲和不捕獲的區別在后面會介紹),例如:待匹配字符串:``
(?:...)匹配子表達式...,但是不捕獲字符(捕獲和不捕獲的區別在后面會介紹)
(?>...)貪婪子表達式,不捕獲,例如正則:(?>[\d]{1,}),待匹配字符:12345,匹配次數1次,匹配結果是:12345。
(?# ... )注釋
(?= ... )零寬度正預測先行斷言。匹配...字符前面位置,注意是位置不是字符,所以寬度為0。例如正則:(?=\d),待匹配字符串:abc123,匹配的位置是下面字符的前面:1,2,3
(?! ... )零寬度負預測先行斷言。匹配后面不是跟著...字符的位置,注意是位置不是字符,所以寬度為0。例如正則:(?=\d),待匹配字符串:abc123,匹配的位置是下面字符的后面:a,b,c,iOS匹配時會自動匹配多一個終止符。
(?<= ... )零寬度正回顧后發斷言。匹配...字符后面位置,注意是位置不是字符,所以寬度為0。例如正則:(?=\d),待匹配字符串:abc123,匹配的位置是下面字符的后面:1,2,3
(?
(?ismwx-ismwx: ... )設置子正則...匹配的flag option。例如:待匹配字符串:test,正則:(?i:TEST),匹配結果:test。正則:(?-i:TEST),匹配不到。用代碼測試時option不要選NSRegularExpressionCaseInsensitive 。
(?ismwx-ismwx)設置之后位置正則匹配的flag option。例如:待匹配字符串:test,正則:(?i)TEST,匹配結果:test。正則:(?-i)TEST,匹配不到,正則:T(?i)EST,匹配不到,因為前面的T是區分大小寫的。用代碼測試時option不要選NSRegularExpressionCaseInsensitive 。
工具
測試工具多中多樣,可以直接在網上搜索‘正則表達式在線檢測’就會出現一堆(如圖:正則表達式在線檢測.png)
正則表達式在線檢測.png
也可以自己寫代碼進行驗證但是比較麻煩每次都要run,為了方便于是筆者就自己寫了個簡單的測試用具如果需要的可以點擊iOS正則表達式檢測工具進行下載。如圖:
iOS正則表達式檢測工具.png
目前沒有做字符串替換功能。
捕獲和不捕獲的區別
捕獲
捕獲會將當前的匹配到的字符儲存起來,在正則表達式中可以用\n進行使用,n是10進制數,第n個捕獲就寫\n,在替換模式中可以用$n,表示第n個捕獲的字符串。
不捕獲
不捕獲則不會儲存匹配到的字符串
例子:
//待匹配字符串:hello//正則:(\w)\1//匹配結果:ll//代碼如下:NSString*string = [NSStringstringWithFormat:@"hello"];NSError*error =NULL;NSString*regexString =@"(\\w)\1";NSRegularExpression*regex = [NSRegularExpressionregularExpressionWithPattern:regexString options:NSRegularExpressionUseUnicodeWordBoundarieserror:&error];NSUIntegerinteger = [regex? numberOfMatchesInString:string options:NSMatchingReportProgressrange:NSMakeRange(0, string.length)];NSArray*matches = [regex matchesInString:string? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? options:0range:NSMakeRange(0, [string length])];for(NSTextCheckingResult* resultinmatches) {NSRangematchRange = [result range];NSString* subString = [string substringWithRange:matchRange];NSLog(@"%@",subString);}
//待匹配字符串:hello//正則:(he)((\w)\3)(o)//替換模式:$1-$2-$3-$4//替換結果:he-ll-l-o//捕獲順序說明:根據"("的順序//代碼如下:NSString*string = [NSStringstringWithFormat:@"hello"];NSError*error =NULL;NSString*regexString =@"(he)((\\w)\\3)(o)";NSRegularExpression*regex = [NSRegularExpressionregularExpressionWithPattern:regexString options:NSRegularExpressionUseUnicodeWordBoundarieserror:&error];NSLog(@"%li",regex.numberOfCaptureGroups);NSLog(@"%@",[regex stringByReplacingMatchesInString:string options:NSMatchingReportProgressrange:NSMakeRange(0, string.length) withTemplate:@"$1-$2-$3-$4"]);
Example
1.國內手機號碼
國內手機號碼都是11位,開頭大概有:
中國移動:134、135、136、137、138、139、150、151、152、157(TD)、158、159、182、183、184、187、178、188、147、1705(虛擬運營商移動號段)
中國聯通:130、131、132、145(數據卡號段)155、156、176、185、186、1709(虛擬運營商聯通號段)
中國電信:133、153、177、180、181、189、134、1700(虛擬運營商電信號段)
參考百度知道
正則如下:
(134|135|136|137|138|139|150|151|152|157|158|159|182|183|184|187|178|188|147|1705|130|131|132|145|155|156|176|185|186|1709|133|153|177|180|181|189|134|1700)\d{8}
分析:
“(134|135|136|137|138|139|150|151|152|157|158|159|182|183|184|187|178|188|147|1705|130|131|132|145|155|156|176|185|186|1709|133|153|177|180|181|189|134|1700)“匹配的號碼開頭?!癨d{8}“匹配后面8個必須是數字
經測試匹配成功。
2.中文
正則表達式:[\u4E00-\u9FA5]
分析:中文編碼和部分日文編碼在\u4E00-\u9FA5范圍
3.郵箱
A@B.C
規則如下:
A可以為數字和字母,且長度至少為1
B可以為數字和字母,且長度至少為1
C為字母或者中文,長度至少為2。(域名后綴長度為1的沒見過)
正則表達式:\b(?i)\w+@\w+\.[A-Z\u4E00-\u9FA5]{2,}\b
分析:
“\b“是邊界,表示郵箱前后都是空格或者其他無內容字符“(?i)“表示后面的字母都是不區分大小寫的“\w+“非字符,長度至少為1“.[A-Z\u4E00-\u9FA5]{2,}“字母或者中文,長度至少為2
4.國內電話
國內電話的格式是:區號-號碼
區號最短3位,最長4。號碼最短5位,最長8位
正則:[\d]{3,4}-[d]{5,8}
分析:
“[\d]{3,4}“ 數字,3到4位“-“分割符-“[d]{5,8}“ 數字,5到8位
5.用戶名,英文開頭,允許輸入數字和英文
正則:^[A-Za-z][A-Za-z0-9]*
分析:
“^[A-Za-z]“字母開頭“[A-Za-z0-9]*“可以輸入數字和英文
6.QQ號
QQ還最短是5位。
正則:[1-9]\d{4,}
分析:
“[1-9]“開頭是不為0的數字“\d{4,}“至少有4個數字
7.身份證
第二代居民身份證居民身份證編碼規則如下:
(1)前1、2位數字表示:所在?。ㄖ陛犑?、自治區)的代碼;
(2)第3、4位數字表示:所在地級市(自治州)的代碼;
(3)第5、6位數字表示:所在區(縣、自治縣、縣級市)的代碼;
(4)第7—14位數字表示:出生年、月、日;
(5)第15、16位數字表示:所在地的派出所的代碼;
(6)第17位數字表示性別:奇數表示男性(1、3、5、7、9),偶數表示女性(0、2、4、6、8);
(7)第18位數字是校檢碼:也有的說是個人信息碼,不是隨計算機的隨機產生,它是 用來檢驗身份證的正確性。校檢碼可以是0—9的數字,有時也用x表示。作為尾號的校驗碼,是由號碼編制單位按統一的公式計算出來的,如果某人的尾號是0-9,都不會出現X,但如果尾號是10,那么就得用X來代替,因為如果用10做尾號,那么此人的身份證就變成了19位。X是羅馬數字的10,用X來代替10,可以保證公民的身份證符合國家標準。
注意:這里最大能輸入2019年。
正則:[1-6][0-7][\d]{4}((19[\d]{2})|(20[0-1][\d]))((0[1-9])|(1[0-2]))((0[1-9])|([1-2]\d)|(3[0-1]))[\d]{3}[\dx]
分析:
“[1-6][0-7]“根據?。ㄖ陛犑?、自治區)的代碼第一位是1-6,第二位是0-7“[\d]{4}“地級市、所在區編碼都是數字“((19[\d]{2})|(20[0-1][\d]))((0[1-9])|(1[0-2]))((0[1-9])|([1-2]\d)|(3[0-1]))“出生日期,最早的是1900/01/01,最晚是2019/12/31“[\d]{3}[\dx]“ 四個數字或者3個數字+x
8.郵政編碼
國內郵政編碼為6位數字
正則\d{6}
分析:都是數字
9.網址
正則為:(?i)\b(http://|https://)?([www.]?)[\w\.\-]+\.[A-Z\u4E00-\u9FA5]{2,}(\:[0-9]+)*(/($|[a-zA-Z0-9\.\,\;\?\'\\+&%\$#\=~_\-]+))*
能匹配:
http://jianshu.com:8080/http://jianshu.com/?a=asdsa&b=asdashttp://簡書.com/
不能匹配:
ftp://jianshu.comftps://jianshu.com
分析:
"(?i)"不區分大小寫"\b"邊界"(http://|https://)?"http://或者https://開頭也可以沒有"([www.]?)"www. 可有可無"[\w\.\-]+"可以出現數字、英文、英文句號、-、中文,至少一個"\.":英文句號."[A-Z\u4E00-\u9FA5]{2,}"英文,中文至少兩個"(\:[0-9]+)*"\、:、數字可有可無"(/($|[a-zA-Z0-9\.\,\;\?\'\\\+&;%\$#\=~_\-]+))*"斜杠/后面可以出現的字符
10.出生日期
格式:yyyy/MM/dd
注意:這里最大能輸入2019年。
正則:((19[\d]{2})|(20[0-1][\d]))/((0[1-9])|(1[0-2]))/((0[1-9])|([1-2]\d)|(3[0-1]))
分析:
"(19[\d]{2})|(20[0-1][\d])"出生年份1900~2019"/"分隔符/"((0[1-9])|(1[0-2]))"出生月份01-12"/"分隔符/"((0[1-9])|([1-2]\d)|(3[0-1]))"出生日期1-31
11.時間
24小時制,時間格式:hh:mm:ss
正則:(([0-1]\d)|(2[0-3])):[0-5]\d:[0-5]\d
分析:
"(([0-1]\d)|(2[0-3]))"00到23小時[0-5]\d""00到59
12.圖片文件名
正則:\w+\.(?i:png|jpg|jpeg|gif)
分析:
"[\w]+"圖片文件名不可以為字符"(?i:png|jpg|jpeg|gif)"后綴名為png、jpg、jpeg、gif中的一種,不區分大小寫。
轉載 http://www.lxweimin.com/p/4eb7e7971146