iOS - 正则表达式

在iOS开发过程中,我们经常会涉及到这样的功能例如:校验手机号、身份证号这样的功能,我们该如何快速有效的实现这样的功能呢?正则表达式是一种通用的、常用的方式,优秀的正则表达式可以让你少写千行代码。这里给大家列举几种常用的正则表达式。

正则表达式应用实例

1. 手机号码正则表达式验证

1) 博主对部分号段做了补充(17、14号段)如有补充 评论即可 我会及时回复

- (BOOL)isMobileNumber:(NSString *)mobileNum
{
    /**
     * 手机号码
     * 移动:134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188
     * 联通:130,131,132,152,155,156,185,186
     * 电信:133,1349,153,180,189
     */
    NSString * MOBILE = @"^1(3[0-9]|5[0-35-9]|8[025-9])\\d{8}$";
    /**
     10         * 中国移动:China Mobile
     11         * 134[0-8],135,136,137,138,139,150,151,157,158,159,182,187,188
     12         */
    NSString * CM = @"^1(34[0-8]|(3[5-9]|5[017-9]|8[278])\\d)\\d{7}$";
    /**
     15         * 中国联通:China Unicom
     16         * 130,131,132,152,155,156,185,186
     17         */
    NSString * CU = @"^1(3[0-2]|5[256]|8[56])\\d{8}$";
    /**
     20         * 中国电信:China Telecom
     21         * 133,1349,153,180,189
     22         */
    NSString * CT = @"^1((33|53|8[09])[0-9]|349)\\d{7}$";
    /**
     25         * 大陆地区固话及小灵通
     26         * 区号:010,020,021,022,023,024,025,027,028,029
     27         * 号码:七位或八位
     28         */

    // NSString * PHS = @"^0(10|2[0-5789]|\\d{3})\\d{7,8}$";

    /**
     29        * 其他号段补充:
     30        * 号段:170、176、177、178、145、147
     31        * 号码:八位
     32        */

     NSString *OT = @"^((17[0678])|(14[57]))\\d{8}$";

    NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];
    NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];
    NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU];
    NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT];
    NSPredicate *regextestot = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", OT];

    if (([regextestmobile evaluateWithObject:mobileNum] == YES)
        || ([regextestcm evaluateWithObject:mobileNum] == YES)
        || ([regextestct evaluateWithObject:mobileNum] == YES)
        || ([regextestcu evaluateWithObject:mobileNum] == YES)
        || ([regextestot evaluateWithObject:mobileNum] == YES))
    {
        return YES;
    }
    else
    {
        return NO;
    }
}

2) 这个是秋秋同学提供的

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

2. 身份证号码正则表达式验证

这个校验是比较全面和详细的

- (BOOL)validateIDCardNumber:(NSString *)value {

    value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    NSUInteger length =0;

    if (!value) {

        return NO;

    }else {

        length = value.length;

        if (length !=15 && length !=18) {

            return NO;

        }

    }

    // 省份代码

    NSArray *areasArray =@[@"11",@"12", @"13",@"14", @"15",@"21", @"22",@"23", @"31",@"32", @"33",@"34", @"35",@"36", @"37",@"41",@"42",@"43", @"44",@"45", @"46",@"50", @"51",@"52", @"53",@"54", @"61",@"62", @"63",@"64", @"65",@"71", @"81",@"82", @"91"];

    NSString *valueStart2 = [value substringToIndex:2];

    BOOL areaFlag = NO;

    for (NSString *areaCode in areasArray) {

        if ([areaCode isEqualToString:valueStart2]) {

            areaFlag = YES;

            break;

        }

    }

    if (!areaFlag) {

        return NO;
    }

    NSRegularExpression *regularExpression;

    NSUInteger numberofMatch;

    int year = 0;

    switch (length) {

        case 15:

            year = [value substringWithRange:NSMakeRange(6,2)].intValue +1900;

            if (year %4 == 0 || (year %100 == 0 && year % 4 == 0)) {

                regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$" options:NSRegularExpressionCaseInsensitive error:nil];//测试出生日期的合法性

            }else {

                regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$"                      options:NSRegularExpressionCaseInsensitive error:nil];//测试出生日期的合法性

            }


            numberofMatch = [regularExpression numberOfMatchesInString:value options:NSMatchingReportProgress range:NSMakeRange(0, value.length)];

            if(numberofMatch >0) {

                return YES;

            }else {

                return NO;

            }

        case 18:

            year = [value substringWithRange:NSMakeRange(6,4)].intValue;

            if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) {

                regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}[0-9Xx]$" options:NSRegularExpressionCaseInsensitive error:nil];//测试出生日期的合法性
            }else {

                regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}19[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}[0-9Xx]$" options:NSRegularExpressionCaseInsensitive error:nil];//测试出生日期的合法性

            }
            numberofMatch = [regularExpression numberOfMatchesInString:value options:NSMatchingReportProgress range:NSMakeRange(0, value.length)];

            if(numberofMatch >0) {

                int S = ([value substringWithRange:NSMakeRange(0,1)].intValue + [value substringWithRange:NSMakeRange(10,1)].intValue) *7 + ([value substringWithRange:NSMakeRange(1,1)].intValue + [value substringWithRange:NSMakeRange(11,1)].intValue) *9 + ([value substringWithRange:NSMakeRange(2,1)].intValue + [value substringWithRange:NSMakeRange(12,1)].intValue) *10 + ([value substringWithRange:NSMakeRange(3,1)].intValue + [value substringWithRange:NSMakeRange(13,1)].intValue) *5 + ([value substringWithRange:NSMakeRange(4,1)].intValue + [value substringWithRange:NSMakeRange(14,1)].intValue) *8 + ([value substringWithRange:NSMakeRange(5,1)].intValue + [value substringWithRange:NSMakeRange(15,1)].intValue) *4 + ([value substringWithRange:NSMakeRange(6,1)].intValue + [value substringWithRange:NSMakeRange(16,1)].intValue) *2 + [value substringWithRange:NSMakeRange(7,1)].intValue *1 + [value substringWithRange:NSMakeRange(8,1)].intValue *6 + [value substringWithRange:NSMakeRange(9,1)].intValue *3;


                int Y = S %11;

                NSString *M =@"F";

                NSString *JYM =@"10X98765432";

                M = [JYM substringWithRange:NSMakeRange(Y,1)];// 判断校验位

                if ([M isEqualToString:[value substringWithRange:NSMakeRange(17,1)]]) {

                    return YES;// 检测ID的校验位

                }else {

                    return NO;
                }
            }else {

                return NO;

            }


        default:

           return NO;

    }

}

这两个正则表达式是比较常用的,其余的正则表达式在以后的使用过程中涉及到我会予以补充,也欢迎大家补充说明,我会及时修改补充。

3. 银行卡号判断(非正则表达式)

luhn算法,银行卡的命名以luhn算法为标准。

//-----------------2016年10月3日更新-----------------
- (BOOL) checkCardNo:(NSString*) cardNo{//luhn算法
    int oddsum = 0;     //奇数求和
    int evensum = 0;    //偶数求和
    int allsum = 0;
    int cardNoLength = (int)[cardNo length];
    int lastNum = [[cardNo substringFromIndex:cardNoLength-1] intValue];

    cardNo = [cardNo substringToIndex:cardNoLength - 1];
    for (int i = cardNoLength -1 ; i>=1;i--) {
        NSString *tmpString = [cardNo substringWithRange:NSMakeRange(i-1, 1)];
        int tmpVal = [tmpString intValue];
        if (cardNoLength % 2 ==1 ) {
            if((i % 2) == 0){
                tmpVal *= 2;
                if(tmpVal>=10)
                    tmpVal -= 9;
                evensum += tmpVal;
            }else{
                oddsum += tmpVal;
            }
        }else{
            if((i % 2) == 1){
                tmpVal *= 2;
                if(tmpVal>=10)
                    tmpVal -= 9;
                evensum += tmpVal;
            }else{
                oddsum += tmpVal;
            }
        }
    }

    allsum = oddsum + evensum;
    allsum += lastNum;
    if((allsum % 10) == 0)
        return YES;
    else
        return NO;
}

正则表达式基础语法规则

【基本语法】

①中括号表示满足其中之一即可,例如[abc],则这个位置可以是a、b、c中任意一个。

②在中括号中,可以通过-连接范围,例如a-z;多个范围之间并列不需要任何分隔符,例如[a-zA-Z]。

③表示重复次数用{x},例如[a-z]{2}表示连续2次;表示重复次数的范围可用{x,y}。

④\d表示数字。

⑤正则表达式默认的是贪婪匹配,例如[a-z]{2,4},如果出现类似abcde2ab这样的字符串,abcd满足最大长度4,因此会作为一个字符串、e是第二个、ab是第三个。

⑥通配符为.(点),.表示除换行符意外的任意字符。

⑦?表示0个或一个前面的字符、+代表至少一个、*代表0个或多个。
例如zo*,*代表o可以是0个或者多个o,也就是说可以是z、zoo。

⑧以什么开头用^,以什么结尾用$。

⑨OC字符串中的特殊字符用\转义。
例如[ ]是正则中的特殊表达式,[是普通的‘[‘字符,而OC中\有特殊含义,需要对\再转义,因此用\[表示‘[‘。

⑩表示中文的范围为 \u4e00-\u9fa5。

?多个匹配条件的并列用|。

匹配时一定要注意贪婪匹配的问题,否则可能会出错。

大家可以按照自己的需求修改相应的正则表达式

NSRegularExpression的使用

首先创建对象,然后通过匹配模式得到NSTextCheckingResult数组,从中取出对象可以拿到匹配到的字符的范围。
下面的代码演示了从一个字符串中找出main和if的范围。

 NSString *code = @"mainjiaoififsiifnelsetifajomainiskkl";
 NSString *pattern1 = @"main|if";
 NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:pattern1 options:0 error:nil];
 NSArray *results = [regex matchesInString:code options:0 range:NSMakeRange(0, code.length)];       
 for (NSTextCheckingResult *result in results) {      
     NSLog(@"%@",NSStringFromRange(result.range));          
 }

集成RegexKitLite

利用系统的对象进行匹配比较麻烦,下面介绍一个强大的第三方库RegexKitLite
①首先从github下载RegexKitLite。
②将文件RegexKitLite.m和.h导入到工程。
③由于该库比较老,不支持ARC,因此应该为RegexKitLite.m添加编译标记-fno-objc-arc进行局部ARC禁止。
④添加动态库libicucore.dylib。
注意③和④都在Build Phases中进行设置,如下图所示:
这里写图片描述
通过以上几步就完成了集成,下面介绍该库的常用方法。
该库是NSString的分类,因此字符串可以直接调用方法,常用的方法有匹配和分割。
①匹配:传入匹配模式pattern即可,可以获取匹配到的字符串和范围。

[str enumerateStringsMatchedByRegex:pattern usingBlock:^(NSInteger captureCount, NSString *const __unsafe_unretained *capturedStrings, const NSRange *capturedRanges, volatile BOOL *const stop) {

     NSRange range = *capturedRanges;
     NSLog(@"%@ %@",*capturedStrings,NSStringFromRange(range));

}];

②分割:有时候有一种需求,需要获取到所有匹配到的内容之外的字串,也就是利用正则内容分割字符串,可以得到匹配到的字串以外的字符串和范围。

[str enumerateStringsSeparatedByRegex:pattern usingBlock:^(NSInteger captureCount, NSString *const __unsafe_unretained *capturedStrings, const NSRange *capturedRanges, volatile BOOL *const stop) {

     NSRange range = *capturedRanges;
     NSLog(@"%@ %@",*capturedStrings,NSStringFromRange(range));

}];
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值