有时我们需要在一大段长文本中过滤出我们需要的字段,或者检验该文本是否符合要求(该文本是否是邮箱,链接,电话号码或身份证),这时候就需要用到正则表达式了,iOS中也加入了相关的类来支持正则表达式的使用。
不会使用正则表达式的读者可以参考该链接 正则表达式30分钟入门教程 ,阅读的时候请注意,在Objectiv-C中,"\"是转义字符,书写正则表达式时应在原式上进行修改,例如要书写"\b",则在Objectiv-C中应为"\\b",
同理,"\bhello world\b"就应写为"\\bhello world\\b"
使用iOS SDK中原生的方法
正则表达式
通过以下两个类我们就能简单的在iOS开发中使用正则表达式来过滤或是验证文本了,本文重点介绍这两个类
- NSRegularExpression
- NSTextCheckingResult
当然,OC中的另外两个类
- NSPredicate
- NSString
也提供了正则表达式应用的方法,文章的后面会略微提及一下。
下面我们来介绍这两个类和他们的基本使用方法,首先我们定义两段文字,一段是将要被过滤的原文本,另一段是用来过滤他的正则表达式文本
NSString *originalString=@"why not creat a project and try it?http://www.baidu.com"; //将要被处理的string
NSString *regex=@"http+:[^\\s]*"; //正则表达式
准备工作完成,接下来介绍一下NSRegularExpression的一些使用方法
获取所有符合规则的字段
NSRegularExpression类常用获取一段文字中符合规则的字段;
例如获取一段文字中全部的邮箱,手机号或是特殊约定的字符串例如微博中的 @用户名。
这些功能主要通过以下几个方法来实现
注意,以下方法返回的结果都是NSTextCheckingResult类型,为方便理解,在注解时我们用“字段”这个词来表示,但它并不是NSString,该类型在文章的后面会讲到。
//枚举每个符合约定的字段,通过block对其进行操作
- (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range usingBlock:(void (^)(NSTextCheckingResult * __nullable result, NSMatchingFlags flags, BOOL *stop))block;
//返回一个存有所有符合约定的字段的NSArray
- (NSArray<NSTextCheckingResult *> *)matchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
//返回符合约定字段的个数
- (NSUInteger)numberOfMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
//返回第一个符合约定的字段
- (nullable NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
//返回第一个符合约定的字段在全文中点NSRange
- (NSRange)rangeOfFirstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
这里我们以第二个方法为例,演示一下如何获取所有符合要求的字段
Example:
//原字段
NSString *testString1 = @"clc_cfzxyq@163.com wcowfjwogjwoiejfiow 12321@qq.com 298349845fwe ctftf:iLoveiOS@qq.com";
NSError *error;
//正则表达式,解析邮箱
NSString* regexString = @"\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
//创建一个正则表达式对象,存储匹配规则
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];
//当解析出的数组至少有一个对象时,即原文本中存在至少一个符合规则的字段
if (array.count != 0) {
for (NSTextCheckingResult* result in array) {
//从NSTextCheckingResult类中取出range属性
NSRange range = result.range;
//从原文本中将字段取出并存入一个NSMutableArray中
[stringArray addObject:[testString1 substringWithRange:range]];
}
}
//打印结果
NSLog(@"%@",stringArray);
}
这样我们就从文本中取出了所有的邮箱,运行结果如下
运行结果
从上面不难看出,NSTextCheckingResult其实就是一个保存搜索结果的类,每一个搜索出的结果都会保存成一个该类的对象,在正则表达式中,只需要用到该类中的range属性,即检索结果在原文中的位置。
替换所有符合规则的字段
NSRegularExpression类中提供了方法来实现用新的字段来替换原文中符合规则的字段。大致有以下几种
//用新字段替换原文本中的对应字段,并返回操作后的NSString
- (NSString *)stringByReplacingMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
//用新字段替换原文本中的对应字段,并返回操作次数(替换字段的个数)
- (NSUInteger)replaceMatchesInString:(NSMutableString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
用第一个方法举例说明
Example:
//需要进行替换的NSString,转换成方法需要的NSMutableString
NSString *testString1 = @"clc_cfzxyq@163.com wcowfjwogjwoiejfiow 12321@qq.com 298349845fwe ctftf:iLoveiOS@qq.com";
NSMutableString* testString2 = [NSMutableString stringWithString:testString1];
NSError *error;
//正则表达式
NSString* regexString = @"\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:&error];
if (regex != nil) {
//使用方法进行文本替换
NSString* resultString = [regex stringByReplacingMatchesInString:testString2 options:NSMatchingReportProgress range:NSMakeRange(0, [testString2 length]) withTemplate:@"uuuuuuuuuuu"];
//打印验证结果
NSLog(@"%@",resultString);
}
这里我们将文本中所有的邮箱都替换成了uuuuuuuuuuu
打印如下
判断字符串是否符合表达式(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
}
通过该方法可以检测文本是否符合某些特定要求(纯数字,纯英文,电话号码,邮箱,身份证等)
这里给出一篇文章,里面有常用的正则表达式示例一个正则表达式测试(只可输入中文、字母和数字)
NSString中使用正则表达式
NSString中使用正则表达式的方法比较轻量级,大致如下
//注意,这些方法里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);
这些方法的用法就像方法名一样耿直,大家都是聪明的程序猿,这里就不多做讲解了。
网友评论
同理,"\bhello world\b"就应写为"\bhello world\b"
?????