iOS正則表達式和NSRegularExpression

這篇文章其實是在學習正則表達式時網(wǎng)上一些資料的整合,所以只能算是一個總結性文章,不是自己原創(chuàng),感謝各位的分享。參考文章和網(wǎng)站在文章結尾。

1.概念

正則表達式:描述符合某些規(guī)則字符串的工具。
正則表達式經(jīng)常用于匹配符合規(guī)則的字符串,然后對符合規(guī)則的字符串進行處理。

在iOS中常用的場景包括:輸入框內輸入內容的限制,特定文本的判定(比如手機號、郵箱、密碼等),對文本內特定字符進行搜索,進行富文本化或替換等。

2.基本規(guī)則

正則表達式基本上由一些特定的字符和表達式構成,所以理解這些字符或表達式是學習的基礎。

元字符:

表1.常用元字符
代碼 說明
. 匹配出換行符意外的任意字符
\w 匹配字母或數(shù)字或下劃線或漢字
\s 匹配任意的空白符
\d 匹配數(shù)字
\b 匹配單詞的開始或結束(不匹配標點符號或者換行符,只匹配一個位置)
^ 匹配字符串的開始
$ 匹配字符串的結束

字符轉義:
如果想使用元字符本身的話,需要用轉義字符,即\*表示*字符。

反義:
有時候需要查找不屬于某個簡單定義的字符類的字符。比如想查找除了數(shù)字以外,其它任意字符都行的情況,這時需要用到反義。

表2.常用反義符號
代碼/語法 說明
\W 匹配任意不是字母、數(shù)字、下劃線、漢字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非數(shù)字的字符
\B 匹配不是單詞開頭或結束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou這幾個字母以外的任意字符

重復:

表3.常用的限定符
代碼/語法 說明
* 重復零次或者更多次
+ 重復一次或者更多次
? 重復零次或一次
{n} 重復n次
{n,} 重復n次或更多次
{n,m} 重復n到m次

范圍:
自定義匹配集合使用[]。比如數(shù)字范圍[0-9]。

分支條件:
如果有幾種規(guī)則,滿足其中任意一種都應當匹配。不同的規(guī)則用 | 隔開,這就是分支條件。
匹配分支條件時,會從左到右的測試每個條件,如果滿足了某個分支的話,就不會再管其他條件。

分組:
可以用()小括號來指定子表達式(即分組)??梢詫Ψ纸M進行重復。

正則表達式常用分組.png

捕獲:
默認情況下每個分組會自動擁有一個組號,從左到右,從1開始。可以用\1代表分組1匹配的文本。
可以使用(?<name>exp)來指定組名,并用\k<name>來捕獲。

零寬斷言
零寬斷言是指定滿足一定條件(即斷言)的位置。
負向零寬斷言:如果我們只是想要確保某個字符沒有出現(xiàn),但并不想去匹配它時就可以使用負向領寬斷言,因為它只匹配一個位置,并不消費任何字符。

注釋
要包含注釋的話最好啟用“忽略模式里的空白符”選項。這樣在#后面到這一行結束的所有文本都將被當成注釋忽略掉。
比如:

  (?<=    # 斷言要匹配的文本的前綴
  <(\w+)> # 查找尖括號括起來的字母或數(shù)字(即HTML/XML標簽)
  )       # 前綴結束
  .*      # 匹配任意文本
  (?=     # 斷言要匹配的文本的后綴
  <\/\1>  # 查找尖括號括起來的內容:前面是一個"/",后面是先前捕獲的標簽
  )       # 后綴結束

貪婪與懶惰
當正則表達式中包含能接受重復的限定服時,通常的行為是(在使整個表達式能得到匹配的前提下)匹配盡可能多的字符。這被稱為貪婪匹配。
懶惰匹配與此相反,在能使整個匹配成功的前提下匹配盡可能少的字符。

表5.懶惰限定符
代碼/語法 說明
*? 重復任意次,但盡可能少重復
+? 重復一次或更多次,但盡可能少重復
?? 重復0次或1次,但盡可能少重復
{n,m}? 重復n到m次,但盡可能少重復
{n,}? 重復n次以上,但盡可能少重復

處理選項
一般會有正則表達式的處理選項,比如:忽略大小、忽略空白、顯示捕獲等,根據(jù)開發(fā)環(huán)境的不同會有不同選項,注意選擇使用。

平衡組/遞歸匹配

  • (?'group')把捕獲的內容命名為group,并壓入堆棧(Stack)
  • (?'-group')從堆棧上彈出最后壓入堆棧的名為group的捕獲內容,如果堆棧本來為空,則本次匹配失敗
  • (?(group)yes|no)如果對戰(zhàn)上存在以名為group的內容的話,繼續(xù)匹配yes內容,否則匹配no內容
  • (?!)零寬負向先行斷言,由于沒有后綴表達式,視圖匹配總是失敗

平衡組常見的應用是匹配HTML。

例子:匹配<>成對出現(xiàn)的字符串。

<                         #最外層的左括號
    [^<>]*                #最外層的左括號后面的不是括號的內容
    (
        (
            (?'Open'<)    #碰到了左括號,在黑板上寫一個"Open"
            [^<>]*       #匹配左括號后面的不是括號的內容
        )+
        (
            (?'-Open'>)   #碰到了右括號,擦掉一個"Open"
            [^<>]*        #匹配右括號后面不是括號的內容
        )+
    )*
    (?(Open)(?!))         #在遇到最外層的右括號前面,判斷黑板上還有沒有沒擦掉的"Open";如果還有,則匹配失敗
>                         #最外層的右括號

3.常用正則表達式

說明 正則表達式
手機號 ^((13[0-9])|(15[012356789])|(17[0,0-9])|(18[0,0-9]))\d{8}$
郵箱 ^([a-z0-9_.-]+)@([\da-z.-]+).([a-z.]{2,6})$
身份證 [1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$)|([1-9]\d{5}\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{2}$
短信驗證碼 \d{6}
中文字符 [\u4e00-\u9fa5]
用戶名 ^[a-z0-9_-]{3,16}$
密碼 ^[a-z0-9_-]{6,18}$
QQ號 [1-9][0-9]{4,}
國內電話 \d{3}-\d{8} \d{4}-\d{7}
URL ^(https?://)?([\da-z.-]+).([a-z.]{2,6})([/\w .-]*)*/?$
IP ^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$

可以點擊下面網(wǎng)址查看更多正則表達式常用正則表達式,使用之前自己最好再驗證一下,有一些也不一定準確。

4.正則表達式在iOS中的應用

iOS中正則表達式有三種使用方式

1). 利用NSPredicate(謂詞)匹配

例如郵箱匹配 :

   NSString *email = @"niji_saki@163.com";
   NSString *regex = @"^([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$";
   NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCH %@", regex];
   BOOL isValid = [predicate evaluateWithObject:email];

2). 利用rangeOfString:option:直接查找

    NSString *searchText = @"http:// Do any additional setup after loading the view, typically from a nib.";
    NSRange range = [searchText rangeOfString:@"(?:[^,])*\\." options:NSRegularExpressionSearch];
    if (range.location != NSNotFound) {
        NSLog(@"%@", [searchText  substringWithRange:range]);
    }

3).使用正則表達式類

    NSString *searchText = @"http:// Do any additional   setup after loading the view, typically from a nib.";   
    NSError *error = NULL;
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(?:[^,])*\\." options:NSRegularExpressionCaseInsensitive error:&error];
    NSTextCheckingResult *result = [regex firstMatchInString:searchText options:0 range:NSMakeRange(0, [searchText length])];
    if (result) {
        NSLog(@"%@\n", [searchText substringWithRange:result.range]);
    } 

第一種需要學習NSPredicate的寫法,第二種之關心匹配結果,第三種效率最高。

5. NSRegularExpression詳解

NSRegularExpression是一個用于匹配Unicode字符串的正則表達式類,該類不可變(immutable)。

NSRegularExoression的基本方法是在目標字符串符合正則表達式是調用一個block,這個block中含有匹配結果信息。此外還有其他一些方法在匹配后返回諸如數(shù)組、匹配數(shù)量、匹配范圍、第一次匹配等結果。還有用來匹配后替換字符串的方法。

匹配結果放在NSTextCheckingResult類中,該類中包含匹配的范圍、數(shù)量、結果類型等變量(iOS11 中新增了rangWithName的方法),同時也提供一些特定的匹配方法,比如針對手機號、日期、地址等的匹配。

NSRegularExpression支持的正則表達式標準在該網(wǎng)站.

具體接口,參見蘋果官方的API。需要注意的是:

  • 當沒有匹配到內容時,返回的range值為{NSNotFound,0}。
  • 當匹配到的內容有多個時,NSTextCheckingResult的range返回匹配內容范圍,range:at:返回匹配內容中的每一個字符的匹配范圍。
  • 匹配方法enumerateMatches(in:options:range:using:) 會根據(jù)options來確定block調用方式,在block中可以設置bool來決定是否停用匹配。
  • stringByReplacingMatchesInString:options:range:withTemplate:方法,template參數(shù)使用$0可以代表匹配的全部字符,使用$1代表第一個字符,依次類推。
  • NSRegularExpression是不可變和線程安全的,因此一個實例可以用在多個線程中進行匹配操作,然而被匹配的字符串在匹配過程是應該是不可變的。

6. iOS正則表達式開源庫


[1].30分鐘了解正則表達式

[2].iOS中正則表達式的三種使用方式

[3].iOS開發(fā)之詳解正則表達式

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容