有時(shí)我們需要在一大段長(zhǎng)文本中過(guò)濾出我們需要的字段,或者檢驗(yàn)該文本是否符合要求(該文本是否是郵箱,鏈接,電話號(hào)碼或身份證),這時(shí)候就需要用到正則表達(dá)式了,iOS中也加入了相關(guān)的類來(lái)支持正則表達(dá)式的使用。
不會(huì)使用正則表達(dá)式的讀者可以參考該鏈接 正則表達(dá)式30分鐘入門教程 ,閱讀的時(shí)候請(qǐng)注意,在Objectiv-C中,"\"是轉(zhuǎn)義字符,書寫正則表達(dá)式時(shí)應(yīng)在原式上進(jìn)行修改,例如要書寫"\b",則在Objectiv-C中應(yīng)為"\\b",
同理,"\bhello world\b"就應(yīng)寫為"\\bhello world\\b"
使用iOS SDK中原生的方法
正則表達(dá)式
通過(guò)以下兩個(gè)類我們就能簡(jiǎn)單的在iOS開(kāi)發(fā)中使用正則表達(dá)式來(lái)過(guò)濾或是驗(yàn)證文本了,本文重點(diǎn)介紹這兩個(gè)類
- NSRegularExpression
- NSTextCheckingResult
當(dāng)然,OC中的另外兩個(gè)類
- NSPredicate
- NSString
也提供了正則表達(dá)式應(yīng)用的方法,文章的后面會(huì)略微提及一下。
下面我們來(lái)介紹這兩個(gè)類和他們的基本使用方法,首先我們定義兩段文字,一段是將要被過(guò)濾的原文本,另一段是用來(lái)過(guò)濾他的正則表達(dá)式文本
NSString *originalString=@"why not creat a project and try it?http://www.baidu.com"; //將要被處理的string
NSString *regex=@"http+:[^\\s]*"; //正則表達(dá)式
準(zhǔn)備工作完成,接下來(lái)介紹一下NSRegularExpression的一些使用方法
獲取所有符合規(guī)則的字段
NSRegularExpression類常用獲取一段文字中符合規(guī)則的字段;
例如獲取一段文字中全部的郵箱,手機(jī)號(hào)或是特殊約定的字符串例如微博中的 @用戶名。
這些功能主要通過(guò)以下幾個(gè)方法來(lái)實(shí)現(xiàn)
注意,以下方法返回的結(jié)果都是NSTextCheckingResult類型,為方便理解,在注解時(shí)我們用“字段”這個(gè)詞來(lái)表示,但它并不是NSString,該類型在文章的后面會(huì)講到。
//枚舉每個(gè)符合約定的字段,通過(guò)block對(duì)其進(jìn)行操作
- (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range usingBlock:(void (^)(NSTextCheckingResult * __nullable result, NSMatchingFlags flags, BOOL *stop))block;
//返回一個(gè)存有所有符合約定的字段的NSArray
- (NSArray<NSTextCheckingResult *> *)matchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
//返回符合約定字段的個(gè)數(shù)
- (NSUInteger)numberOfMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
//返回第一個(gè)符合約定的字段
- (nullable NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
//返回第一個(gè)符合約定的字段在全文中點(diǎn)NSRange
- (NSRange)rangeOfFirstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
這里我們以第二個(gè)方法為例,演示一下如何獲取所有符合要求的字段
Example:
//原字段
NSString *testString1 = @"clc_cfzxyq@163.com wcowfjwogjwoiejfiow 12321@qq.com 298349845fwe ctftf:iLoveiOS@qq.com";
NSError *error;
//正則表達(dá)式,解析郵箱
NSString* regexString = @"\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
//創(chuàng)建一個(gè)正則表達(dá)式對(duì)象,存儲(chǔ)匹配規(guī)則
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:&error];
if (regex != nil) {
//用該方法解析出所有
NSArray* array = [regex matchesInString:testString1 options:NSMatchingReportProgress range:NSMakeRange(0, [testString1 length])];
NSMutableArray* stringArray = [[NSMutableArray alloc] init];
//當(dāng)解析出的數(shù)組至少有一個(gè)對(duì)象時(shí),即原文本中存在至少一個(gè)符合規(guī)則的字段
if (array.count != 0) {
for (NSTextCheckingResult* result in array) {
//從NSTextCheckingResult類中取出range屬性
NSRange range = result.range;
//從原文本中將字段取出并存入一個(gè)NSMutableArray中
[stringArray addObject:[testString1 substringWithRange:range]];
}
}
//打印結(jié)果
NSLog(@"%@",stringArray);
}
這樣我們就從文本中取出了所有的郵箱,運(yùn)行結(jié)果如下

從上面不難看出,NSTextCheckingResult其實(shí)就是一個(gè)保存搜索結(jié)果的類,每一個(gè)搜索出的結(jié)果都會(huì)保存成一個(gè)該類的對(duì)象,在正則表達(dá)式中,只需要用到該類中的range屬性,即檢索結(jié)果在原文中的位置。
替換所有符合規(guī)則的字段
NSRegularExpression類中提供了方法來(lái)實(shí)現(xiàn)用新的字段來(lái)替換原文中符合規(guī)則的字段。大致有以下幾種
//用新字段替換原文本中的對(duì)應(yīng)字段,并返回操作后的NSString
- (NSString *)stringByReplacingMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
//用新字段替換原文本中的對(duì)應(yīng)字段,并返回操作次數(shù)(替換字段的個(gè)數(shù))
- (NSUInteger)replaceMatchesInString:(NSMutableString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
用第一個(gè)方法舉例說(shuō)明
Example:
//需要進(jìn)行替換的NSString,轉(zhuǎn)換成方法需要的NSMutableString
NSString *testString1 = @"clc_cfzxyq@163.com wcowfjwogjwoiejfiow 12321@qq.com 298349845fwe ctftf:iLoveiOS@qq.com";
NSMutableString* testString2 = [NSMutableString stringWithString:testString1];
NSError *error;
//正則表達(dá)式
NSString* regexString = @"\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:&error];
if (regex != nil) {
//使用方法進(jìn)行文本替換
NSString* resultString = [regex stringByReplacingMatchesInString:testString2 options:NSMatchingReportProgress range:NSMakeRange(0, [testString2 length]) withTemplate:@"uuuuuuuuuuu"];
//打印驗(yàn)證結(jié)果
NSLog(@"%@",resultString);
}
這里我們將文本中所有的郵箱都替換成了uuuuuuuuuuu
打印如下

判斷字符串是否符合表達(dá)式(NSPredicate)
這里我們用到NSPredicate類的方法
NSString *testString = @"clc_cfzxyq@163.com";
NSString *regex = @"\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
//注意這里的格式 @"SELF MATCHES %@", regex
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
//判斷
BOOL isValid = [predicate evaluateWithObject: testString];
if (isValid) {
NSLog(@"YES");//是則打印YES
}
通過(guò)該方法可以檢測(cè)文本是否符合某些特定要求(純數(shù)字,純英文,電話號(hào)碼,郵箱,身份證等)
這里給出一篇文章,里面有常用的正則表達(dá)式示例一個(gè)正則表達(dá)式測(cè)試(只可輸入中文、字母和數(shù)字)
NSString中使用正則表達(dá)式
NSString中使用正則表達(dá)式的方法比較輕量級(jí),大致如下
//注意,這些方法里options的值取NSRegularExpressionSearch
- (NSRange)rangeOfString:(NSString *)searchString options:(NSStringCompareOptions)mask;
- (NSRange)rangeOfString:(NSString *)searchString options:(NSStringCompareOptions)mask range:(NSRange)searchRange;
- (NSRange)rangeOfString:(NSString *)searchString options:(NSStringCompareOptions)mask range:(NSRange)searchRange locale:(nullable NSLocale *)locale NS_AVAILABLE(10_5, 2_0);
這些方法的用法就像方法名一樣耿直,大家都是聰明的程序猿,這里就不多做講解了。
參考文獻(xiàn):oc的正則表達(dá)式(RegularExpression)