浅谈iOS中的正则表达式

正则表达式,在各个领域应用都很广泛,其可以快速帮我们查找或者过滤掉某些相关信息。在iOS的开发中也同样经常遇到。例如早期我在开发音乐播放器的时候,使用正则表达式来过滤歌词信息。以及后面陆续出现的IP地址的检测,密码安全检查等等。

今天来和大家一起总结和分享相关经典的正则表达式。首先,我们需要一些基础知识,即正则表达式的基本语法。这里有一个快速入门的网站正则表达式30分钟入门教程,请务必先进行基础知识的学习。

下面,我们来通过实际例子来进行学习和总结。

//邮箱  
+ (BOOL) validateEmail:(NSString *)email  
{  
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";  
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];  
    return [emailTest evaluateWithObject:email];  
}  

注解:[A-Z0-9a-z._%+-]指大写或小写以及数字,以及._%+-这些字符开头,后面那个+号指这样的字符至少要有一个。后面紧接着要有一个@符号。[A-Za-z0-9.-]+指大写或小写以及数字,以及.-这些字符后面的+号指这些字符至少有一个。紧接着是一个.[A-Za-z]{2,4}指2到4位的字母。
测试:@"1._+-%@qq.-.com"这就是一个正确的邮箱格式(哈哈,这和大家通常见到的google或者网易邮箱是不是很不一样,但它的确就是正常的格式)

//手机号码验证  
+ (BOOL) validateMobile:(NSString *)mobile  
{  
    //手机号以13, 15,18开头,八个 \d 数字字符  
    NSString *phoneRegex = @"^((13[0-9])|(15[^4,\\D])|(18[0,0-9]))\\d{8}$";  
    NSPredicate *phoneTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",phoneRegex];  
    return [phoneTest evaluateWithObject:mobile];  
} 

注解:^指字符串的开头。(13[0-9])指13开头后面紧跟着任意一个数字,|(15[^4,\D])指或者以15开头,后面紧跟着一个不为4的数字(4后面的逗号其实也可以写成&&,\D是指非数字类的字符,再与前面的^一匹配,负负得正,就成了数字了)。|(18[0,0-9]))指或者以18开头,后面紧跟着任意一个数字(其实这里可以直接写成[0,9]),\d{8}$指以8位任意数字结束
测试:@"15488762583"这不是一个正确的手机号码。同时我们可以把表达式精简为如下@"^((13[0-9])|(15[^4,\\D])|(18[0-9]))\\d{8}$"

  //车牌号验证  
+ (BOOL) validateCarNo:(NSString *)carNo  
{  
    NSString *carRegex = @"^[\u4e00-\u9fa5]{1}[a-zA-Z]{1}[a-zA-Z_0-9]{4}[a-zA-Z_0-9_\u4e00-\u9fa5]$";  
    NSPredicate *carTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",carRegex];  
    NSLog(@"carTest is %@",carTest);  
    return [carTest evaluateWithObject:carNo];  
} 

注解:\u4e00-\u9fa5指中文字符区间,请参考这篇文章汉字区间,文中提到了关于中文的正则表达式, 应该是^[\u4E00-\u9FFF]+$, 和论坛里常被人提起的^[\u4E00-\u9FA5]+$很接近.于是,我们就可以这样理解这里的内容,以一个汉字开头,后面接一个字母,后台接4个字母或者数字,再以一个字母、数字或者汉字结束。
测试:@"冏C2345途"是一个正确的车牌号(哈哈,是不是离现实有点远)

//身份证号  
+ (BOOL) validateIdentityCard: (NSString *)identityCard  
{  
    BOOL flag;  
    if (identityCard.length <= 0) {  
        flag = NO;  
        return flag;  
    }  
    NSString *regex2 = @"^(\\d{14}|\\d{17})(\\d|[xX])$";  
    NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];  
    return [identityCardPredicate evaluateWithObject:identityCard];  
} 

注解:这里可以理解为以14位或者17位数字开头,以一个数字或者字母x或者字母X结束(共15位或者18位)。

需要注意的地方

1、[] {} () . , 这些在正则表达式中属于关键字,如果要把它们当成字符来判断,需要进行转义,例如在前面加上反斜杠 [。
其中.是另一个元字符,匹配除了换行符以外的任意字符。
举例说明

        var str = " [01:21] 快乐的生活 [02:12] 终于等到你"
        var regex:NSRegularExpression = NSRegularExpression(pattern: "\\[[^\\[\\]]+\\]", options: NSRegularExpressionOptions.CaseInsensitive, error: nil)!

这个例子就是查找用[]包含的字符在字符串中的位置

2、后续还有host地址检测的正则表达式等非常实用的功能,例如^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$
更多实用的正则表达式组合,请参考最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等

3、在iOS中使用正则表达式的相关代码如下

    NSString *str = @"There has no iPhone and iPad on desktop";
    NSRegularExpression *iExpression = [NSRegularExpression regularExpressionWithPattern:@"i[\\p{Alphabetic}&&\\p{Uppercase}][\\p{Alphabetic}]+" options:0 error:NULL];
    [iExpression enumerateMatchesInString:str options:0 range:NSMakeRange(0, str.length) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
        // Add red highlight color
        [self addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:result.range];
    }];

其中,\p{Alphabetic}是英文字母的意思


另外一种使用方式是这样的

NSString email  @nijino_saki@163.com”; 
NSString *regex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"; 
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex]; 
BOOL isValid = [predicate evaluateWithObject:email];

这里可以直接用于词法较验


第三种方式是这样的

NSString *searchText = @"// 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]); 
}

4、其实正则表达式的实现是依靠一个状态机来作解析的。
其中会包含语法分析、编译、运行这些过程,所以一个过于复杂的正则表达式的验证可能会带来性能问题。所以精简的语法,或者在线程中运行是一个不错的选择,而且Regex本身是线程安全的。

2015-11-08 11:37250