美文网首页
iOS中的正则表达式

iOS中的正则表达式

作者: 小小棒棒糖 | 来源:发表于2018-10-24 10:55 被阅读0次

    正则表达式也用过一段时间了,不同的语言中用起来并不相同,这里姑且做为iOS正则的一个总结贴。

    [TOC]

    iOS中的正则表达式

    正则语法

    1. 基本

    我把同类正则符号做了分组列举,以/作为分隔

    元字符 描述
    \ 转义符 如\\n为\n,单\n为换行符
    ^ / $ 行首与行尾
    ? / * / + / {n} / {m,n} 零次或一次/>=0次/>=1次/n次/m-n次,mn可省略一端限制
    ? 跟在(*,+,?,{n},{n,},{n,m})后面时,为非贪婪模式。如,对于“oooo”,o+得到oooo,o+?得到o
    x|y 匹配x或y
    && 字符组与运算,有些语言支持,比如&&+[] Java中就支持,但JavaScript不支持。验证iOS中支持。
    [xyz1-9] 匹配xyz或者1-9数字其中一个
    [^xyz] 非xyz
    \b / \B 单词/非单词的边界,可放前后。如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”
    \d / \D 数字/非数字
    \s / \S 不可见/可见字符。\s不可见,等价于[ \f\n\r\t\v]
    \w / \W \w包括下划线的字符,包括字母/数字/中文/下划线,不包括emoj。
    . 匹配任何单个字符(注意不包括换行符)

    1.1 &&+[]运算

    对于&&+[]运算符,原话是这样描述的:

    有些语言支持,比如&&+[] Java中就支持,但JavaScript不支持。
    示例7:匹配英文字母中除去元音字符的字符
    [[a-z]&&[^aeiou]] // a-z 且排除掉5个元音字符aeiou
    

    我的验证,iOS中是支持的。

    NSPredicate *predicate1 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[[a-z ]&&[^acdkn]]+"];
    NSLog(@"测试&&:%d", [predicate1 evaluateWithObject:@"better boy"]);
    NSLog(@"测试&&:%d", [predicate1 evaluateWithObject:@"better boy run"]);
    
    NSPredicate *predicate11 = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"[1234567890&&[^6]]+"];
    NSLog(@"测试&&:%d", [predicate11 evaluateWithObject:@"1234567890"]);
    NSLog(@"测试&&:%d", [predicate11 evaluateWithObject:@"123457890"]);
    /*打印结果:
    2018-10-11 14:15:03.206346+0800 WEEX_TEST[96757:22569846] 测试&&:1
    2018-10-11 14:15:03.206425+0800 WEEX_TEST[96757:22569846] 测试&&:0
    2018-10-11 14:15:03.206534+0800 WEEX_TEST[96757:22569846] 测试&&:0
    2018-10-11 14:15:03.206600+0800 WEEX_TEST[96757:22569846] 测试&&:1
    */
    

    2. 进阶

    元字符 描述
    \f/\n/\r/\t/\v 换页符/换行符/回车符/制表符/垂直制表符
    \xn 十六进制转义值,可表示ASCII编码。如:“\x41”匹配“A”。
    \un 四个十六进制数字表示的Unicode字符。如,\u00A9
    \n 标识一个八进制转义值或引用。注:引用优先于转义,如前面不足n个表达式,才转义生效。
    \num 对所获取的匹配的引用。例如,"78aaa",用@"(.)\\1",得到"aa"。🤣😌456678aa87aaaas,用@"(\d)(\d)(\w)\3\2\1",得到"78aa87"。注:引用优先于转义,如前面不足n个表达式,才转义生效。

    3. 非获取匹配

    非获取匹配,匹配pattern但不获取匹配结果.

    元字符 描述
    ?:pattern 例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
    ?=pattern 正向肯定预查.
    ?<=pattern 反向肯定预查.
    ?!pattern 正向否定预查.
    ?<!pattern 反向否定预查.

    其中,包含了4个概念:

    • 正向 --> 在查找目标右侧
    • 反向 --> 在查找目标左侧
    • 肯定 --> 是pattern
    • 否定 --> 不是pattern

    正常读起来就是:

    • 正向肯定预查:在目标右侧是pattern
    • 反向肯定预查:在目标左侧是pattern
    • 正向否定预查:在目标右侧不是pattern
    • 反向否定预查:在目标左侧不是pattern

    <span id = "jump_find_emoji_code"></span>
    来个例子,查找中括号内的emoji表情,但不要中括号

    //用到了:正向肯定预查?=与反向肯定预查?<=
    NSString *sourceStr3 = @"我是一个[笑脸],[强],你是一个[自信]";
    NSString *pattern = @"(?<=\\[).*?(?=\\])";
    NSRegularExpression *regex3 = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
    NSArray<NSTextCheckingResult *> *results3 = [regex3 matchesInString:sourceStr3 options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr3.length)];
    for (NSTextCheckingResult *result in results3) {
        NSLog(@"中括号内:%@", [sourceStr3 substringWithRange:result.range]);
    }
    /*打印结果:
    2018-10-10 16:08:35.145447+0800 WEEX_TEST[15000:20387096] 中括号内:笑脸
    2018-10-10 16:08:35.145550+0800 WEEX_TEST[15000:20387096] 中括号内:强
    2018-10-10 16:08:35.145652+0800 WEEX_TEST[15000:20387096] 中括号内:自信
    */
    
    

    分解:

    (?<=\\[)    //目标左侧是[
    .*          //查找任意数量的任意字符,也是我们想查询的目标
    ?           //非贪婪。如果去掉?,会得到:笑脸],[强],你是一个[自信
    (?=\\])     //目标右侧是]
    

    升级一下:如果需求emoji表情为两个字,如何丢弃一个字的emoji呢?如果有些干扰的或者一半的中括号,如何规避掉呢?

    NSString *sourceStr3 = @"我是一个[笑脸],[[强]],][][[∑®†]你是一个[自信]";
    NSString *pattern = @"(?<=\\[)([^\\[\\]]{2,}?)(?=\\])";
    NSRegularExpression *regex3 = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil];
    NSArray<NSTextCheckingResult *> *results3 = [regex3 matchesInString:sourceStr3 options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr3.length)];
    for (NSTextCheckingResult *result in results3) {
        NSLog(@"中括号内:%@", [sourceStr3 substringWithRange:result.range]);
    }
    /*打印结果:
    2018-10-10 16:52:30.027836+0800 WEEX_TEST[27737:20549839] 中括号内:笑脸
    2018-10-10 16:52:30.027931+0800 WEEX_TEST[27737:20549839] 中括号内:∑®†
    2018-10-10 16:52:30.027984+0800 WEEX_TEST[27737:20549839] 中括号内:自信
    */
    

    用到了[^]符号,去否定[];用到了{2,},去匹配两位以上。其实{2,}后面的那个非贪婪?也可以去掉的,因为碰到[]就匹配结束了,不会出现贪婪∑®†]你是一个[自信进来的情况。

    iOS中正则的三种表现形式

    1. [string rangeOfString: options:]查找字符串范围,返回第一个匹配成功的range
    2. NSPredicate谓词匹配数组与字符串。
    3. NSRegularExpression匹配。

    1. [string rangeOfString: options:]

    例查找第一个出现的数字:

        NSString *sourceStr2 = @"123元45678秒09分";
        NSString *regex2 = @"(?<=“).*(?=”)";
        NSRange range2 = [sourceStr2 rangeOfString:regex2 options:NSRegularExpressionSearch];
        if (range2.length > 0) {
            NSLog(@"%@", [sourceStr2 substringWithRange:range2]);
        }
        //打印:123
    

    1.1 出现的option参数

    typedef NS_OPTIONS(NSUInteger, NSStringCompareOptions) {
        NSCaseInsensitiveSearch = 1,  //不区分大小写比较
        NSLiteralSearch = 2,       //逐字节比较 区分大小写
        NSBackwardsSearch = 4,     //从字符串末尾开始搜索
        NSAnchoredSearch = 8,      //搜索限制范围的字符串
        NSNumericSearch = 64,     //按照字符串里的数字为依据,算出顺序。例如 Foo2.txt < Foo7.txt < Foo25.txt
        NSDiacriticInsensitiveSearch    NS_ENUM_AVAILABLE(10_5, 2_0) = 128,//忽略 "-" 符号的比较
        NSWidthInsensitiveSearch    NS_ENUM_AVAILABLE(10_5, 2_0) = 256,//忽略字符串的长度,比较出结果
        NSForcedOrderingSearch  NS_ENUM_AVAILABLE(10_5, 2_0) = 512,//忽略不区分大小写比较的选项,并强制返回 NSOrderedAscending 或者 NSOrderedDescending
        NSRegularExpressionSearch   NS_ENUM_AVAILABLE(10_7, 3_2) = 1024    /*只能应用于 rangeOfString:..., stringByReplacingOccurrencesOfString:...和 replaceOccurrencesOfString:... 方法。
        使用通用兼容的比较方法,如果设置此项,可以去掉 NSCaseInsensitiveSearch 和 NSAnchoredSearch*/
    };
    

    2. NSPredicate

    ==NSPredicate下,例子引自: sunny_zl==

    其中,只有MATCHES时为正则匹配,这儿也把NSPredicate用法罗列下。

    2.1 比较运算符

    包括:

    1. >=
    2. <=
    3. >
    4. <
    5. !=
    6. ==
    7. BETWEEN {下限,上限} //大于或等于下限
    

    例:

    NSNumber *testNumber = @123;
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF = 123"];
    if ([predicate evaluateWithObject:testNumber]) {
        NSLog(@"testString:%@", testNumber);
    }
    //结果:testString:123
    

    2.2 逻辑运算符

    包括:

    1. AND &&
    2. OR ||
    3. NOT !
    

    例:

    NSArray *testArray = @[@1, @2, @3, @4, @5, @6];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];
    NSArray *filterArray = [testArray filteredArrayUsingPredicate:predicate];
    NSLog(@"filterArray:%@", filterArray);
    //结果为:(3, 4)
    

    2.3 字符串比较运算符

    包括:

    1. BEGINSWITH   //以指定的字符串开头
    2. ENDSWITH     //以指定的字符串结尾
    3. CONTAINS     //包含指定的字符串
    4. LIKE         //是否匹配指定的字符串模板。?代表一个字符和*代表任意多个字符。如:name LIKE '*ac*'中间包含ac;name LIKE '?ac*'匹配第2个位置开始为ac
    5. MATCHES      //匹配指定的正则表达式
    

    注:字符串比较都是区分大小写和重音符号的。
    如:cafécafe是不一样的,Cafecafe也是不一样的。

    cd符号:[c]是不区分大小写,[d]是不区分重音符号。如:name LIKE[cd] 'cafe'

    如:

    //简单判断是否手机号
    - (BOOL)checkPhoneNumber:(NSString *)phoneNumber {
        NSString *regex = @"^[1][3-8]\\d{9}$";
        NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
        return [pred evaluateWithObject:phoneNumber];
    }
    

    2.4 集合运算符

    包括:

    1. ANY、SOME:集合中任意一个元素满足条件,就返回YES。
    2. ALL:集合中所有元素都满足条件,才返回YES。
    3. NONE:集合中没有任何元素满足条件就返回YES。如:NONE person.age < 18
    4. IN只有当左边表达式或值出现在右边的集合中才会返回YES。
    

    如:

    //查找不在filterArray中元素
    NSArray *filterArray = @[@"ab", @"abc"];
    NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
    NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);
    //输出:( a, abcd )
    

    2.5 谓词中使用占位符参数

    包括:

    %K:用于动态传入属性名
    %@:用于动态设置属性值
    $VALUE: 使用动态改变的属性值
    

    如:

    //定义一个property来存放属性名,定义一个value来存放值
    NSString *property = @"name";
    NSString *value = @"Jack";
    //该谓词的作用是如果元素中property属性含有值value时就取出放入新的数组内,这里是name包含Jack
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"%K CONTAINS %@", property, value];
    NSArray *newArray = [array filteredArrayUsingPredicate:pred];
    NSLog(@"newArray:%@", newArray);
    
    //------------- 传递VALUE值 -------------
    // 创建谓词,属性名改为age,要求这个age包含$VALUE字符串,子谓词传递value值
    NSPredicate *predTemp = [NSPredicate predicateWithFormat:@"%K > $VALUE", @"age"];
    // 指定$VALUE的值为 25
    NSPredicate *pred1 = [predTemp predicateWithSubstitutionVariables:@{@"VALUE" : @25}];
    NSArray *newArray1 = [array filteredArrayUsingPredicate:pred1];
    NSLog(@"newArray1:%@", newArray1);
    

    2.6 基本用法

    //字符串内查找 查找数字
    NSString *regex = @"\d";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    BOOL match = [predicate evaluateWithObject:sourceString];
    
    //数字比较 判断是否100-200间
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF BETWEEN {100, 200}"];
    
    //过滤数组内字符串 在filterArray中
    NSArray *filterArray = @[@"ab", @"abc"];
    NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF IN %@", filterArray];
    NSArray *newArray = [array filteredArrayUsingPredicate:predicate];
    
    //过滤数组内字典 查找name张姓的
    NSArray *array = @[@{@"name" : @"zhangsan", @"age" : @"10"},
                       @{@"name" : @"lisi",     @"age" : @"11"},
                       @{@"name" : @"wangwu",   @"age" : @"12"}];
     
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name CONTAINS[c] 'zhang'"];
    NSArray *results = [array filteredArrayUsingPredicate:predicate];
    
    //过滤数组内对象,同数组内字典,不再举例
    
    //对象的key比较 对象的age大于25
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age > 25"];
    

    3. NSRegularExpression

    3.1 查找匹配

    1. 查找第一个匹配范围。 
    - (NSRange)rangeOfFirstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
    
    2. 查找第一个匹配结果。
    - (nullable NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
    
    3. 查找满足条件总次数。
    - (NSUInteger)numberOfMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
    
    4. 查找所有匹配结果。
    - (NSArray<NSTextCheckingResult *> *)matchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range;
    
    5. 查找并通过block遍历结果。
    - (void)enumerateMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range usingBlock:(void (NS_NOESCAPE ^)(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL *stop))block;
    

    还发现了一个方法:+ (NSString *)escapedPatternForString:(NSString *)string;,这家伙是用来做什么的呢?它是帮助我们添加转义符的!

    如:

    NSString *ttt = @"\\d{4,}\n";
    NSLog(@"%@", ttt);
    NSLog(@"%@", [NSRegularExpression escapedPatternForString:ttt]);
    /*打印结果:
    2018-10-10 17:25:16.870223+0800 WEEX_TEST[37135:20678832] \d{4,}
    2018-10-10 17:25:16.870438+0800 WEEX_TEST[37135:20678832] \\d\{4,\}
    */
    

    3.2 查找替换

    1. 字符串替换,返回一个新串
    - (NSString *)stringByReplacingMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
    
    2. 可变字符串替换,返回操作次数
    - (NSUInteger)replaceMatchesInString:(NSMutableString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)templ;
    
    3. 自定义替换功能(没搞懂,用了后没发现什么作用)
    - (NSString *)replacementStringForResult:(NSTextCheckingResult *)result inString:(NSString *)string offset:(NSInteger)offset template:(NSString *)templ;
    
    4. 转换为正则表达式字符串
    + (NSString *)escapedTemplateForString:(NSString *)string;
    

    例子1,查找并替换数字:

    NSString *sourceStr = @"123元45678秒09分";
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+" options:NSRegularExpressionCaseInsensitive error:nil];
    NSArray<NSTextCheckingResult *> *results = [regex matchesInString:sourceStr options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr.length)];
    for (NSTextCheckingResult *result in results) {
        NSLog(@"%@", [sourceStr substringWithRange:result.range]);
    }
        
    NSString *replaced = [regex stringByReplacingMatchesInString:sourceStr options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr.length) withTemplate:@"<<-->>"];
    NSLog(@"replaced:%@", replaced);
    /*打印结果:
    2018-10-10 17:40:30.122470+0800 WEEX_TEST[41545:20749671] 123
    2018-10-10 17:40:30.122601+0800 WEEX_TEST[41545:20749671] 45678
    2018-10-10 17:40:30.122712+0800 WEEX_TEST[41545:20749671] 09
    2018-10-10 17:40:30.122858+0800 WEEX_TEST[41545:20749671] replaced:<<-->>元<<-->>秒<<-->>分
    */
    

    例子2,可变字符串查找并替换

    NSMutableString *sourceStr2 = [@"123元45678秒09分" mutableCopy];
    NSInteger replaceNum = [regex replaceMatchesInString:sourceStr2 options:NSMatchingReportProgress range:NSMakeRange(0, sourceStr.length) withTemplate:@"<<-->>"];
    NSLog(@"replaceNum:%ld replaced:%@", replaceNum, sourceStr2);
    /*打印结果:
    2018-10-10 17:45:56.019120+0800 WEEX_TEST[43137:20772997] replaceNum:3 replaced:<<-->>元<<-->>秒<<-->>分
    */
    

    3.3 出现的option参数

    以下说明引自:roc_lei

    NSRegularExpressionOptions:

    typedef NS_OPTIONS(NSUInteger, NSRegularExpressionOptions) {
       NSRegularExpressionCaseInsensitive             = 1 << 0,     /*不区分字母大小写的模式*/
       NSRegularExpressionAllowCommentsAndWhitespace  = 1 << 1,     /*忽略掉正则表达式中的空格和#号之后的字符*/
       NSRegularExpressionIgnoreMetacharacters        = 1 << 2,     /*将正则表达式整体作为字符串处理*/
       NSRegularExpressionDotMatchesLineSeparators    = 1 << 3,     /*允许.匹配任何字符,包括换行符 */
       NSRegularExpressionAnchorsMatchLines           = 1 << 4,     /*允许^和$符号匹配行的开头和结尾*/
       NSRegularExpressionUseUnixLineSeparators       = 1 << 5,     /*设置\n为唯一的行分隔符*/
       NSRegularExpressionUseUnicodeWordBoundaries    = 1 << 6      /*使用Unicode TR#29标准作为词的边界,否则所有传统正则表达式的词边界都有效*/
    };
    

    NSMatchingOptions:

    typedef NS_OPTIONS(NSUInteger, NSMatchingOptions) {
       NSMatchingReportProgress         = 1 << 0, //找到最长的匹配字符串后调用block回调
       NSMatchingReportCompletion       = 1 << 1, //找到任何一个匹配串后都回调一次block
       NSMatchingAnchored               = 1 << 2, //从匹配范围的开始处进行匹配
       NSMatchingWithTransparentBounds  = 1 << 3, //允许匹配的范围超出设置的范围
       NSMatchingWithoutAnchoringBounds = 1 << 4  //禁止^和$自动匹配行还是和结束
    };
    

    NSMatchingFlags:

    typedef NS_OPTIONS(NSUInteger, NSMatchingFlags) {
       NSMatchingProgress               = 1 << 0, //匹配到最长串后被设置     
       NSMatchingCompleted              = 1 << 1, //全部分配完成后被设置    
       NSMatchingHitEnd                 = 1 << 2, //匹配到设置范围的末尾时被设置   
       NSMatchingRequiredEnd            = 1 << 3, //当前匹配到的字符串在匹配范围的末尾时被设置     
       NSMatchingInternalError          = 1 << 4  //由于错误导致的匹配失败时被设置   
    };
    

    iOS中正则使用实例

    一般使用场景分为两种,全匹配与输入框内边输入边匹配。
    实例这里,只演示简单正则使用规则,不做完全严格的匹配。

    1. 全匹配

    1.1 是否有效身份证号

    //15或18位身份证:第一位为1-9,中间13或16位数字,最后一位为0-9xX
    BOOL validateIdentityCard(NSString *identityCard){
        NSString *regex2 = @"^[1-9](\\d{13}|\\d{16})[0-9xX]$";
        NSPredicate *identityCardPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex2];
        return [identityCardPredicate evaluateWithObject:identityCard];
    }
    

    1.2 是否有效手机号

    BOOL validatePhoneNumber(NSString *phone) {
        NSString *regex = @"^1[34578]\\d{9}$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        return [predicate evaluateWithObject:phone];
    }
    

    1.3 是否有效6-16位密码

    //6-16位密码,只允许输入大小写与数字,并且大小写与数字至少每种一个
    BOOL validatePWD(NSString *pwd) {
        NSString *regex = @"^(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])[a-zA-Z0-9]{6,16}$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        return [predicate evaluateWithObject:pwd];
    }
    

    1.4 金额数字添加逗号分隔符

    NSString *sourceText = @"1234567890";
    NSString *pattern3 = @"\\B(?=(?:\\d{3})+(?!\\d))";
    NSRegularExpression *regex3 = [NSRegularExpression regularExpressionWithPattern:pattern3 options:NSRegularExpressionCaseInsensitive error:nil];
    NSArray<NSTextCheckingResult *> *results3 = [regex3 matchesInString:sourceText options:NSMatchingReportProgress range:NSMakeRange(0, sourceText.length)];
    NSString *replaced = [regex3 stringByReplacingMatchesInString:sourceText options:NSMatchingReportProgress range:NSMakeRange(0, sourceText.length) withTemplate:@","];
    NSLog(@"replaced:%@", replaced);
    /*打印结果:
    2018-10-11 10:52:32.896514+0800 WEEX_TEST[38772:22081217] replaced:1,234,567,890
    */
    

    1.5 查找中括号内emoji表情

    见<a href="#jump_find_emoji_code" target="_self">非获取匹配中的查找emoji</a>

    1.6 限最多8位金额,最多两位小数,第一位不能为.

    //控制8位金额,最多两位小数,只能输入数字与.,第一位不能为.或+-
    NSString *toString = [textField.text stringByReplacingCharactersInRange:range withString:string];
    NSString *stringRegex = @"(([0]|(0[.]\\d{0,2}))|([1-9]\\d{0,7}(([.]\\d{0,2})?)))?";
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", stringRegex];
    if ([predicate evaluateWithObject:toString]) {
        return YES;
    }
    return NO;
    

    2. 边输入边匹配

    边输入边匹配的场景还是挺多的,比如限制输入框输入手机号码,输入金额,输入密码,或输入身份证号。

    它与全匹配不同,需要在输入过程中,边输入边验证。当检测到不匹配时,拒绝用户输入,所以用:-textField:shouldChangeCharactersInRange:replacementString:。还要支持回车退格等。注意:正则检测的是替换后的string

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
        //过滤字符
        if ([string isEqualToString:@""] ||    //按退格可以改变
            [string isEqualToString:@"\n"]) {  //按回车可以改变
            return YES;
        }
        //因为要匹配的是输入后字符,所以需要替换操作toString
        NSString *toString = [textField.text stringByReplacingCharactersInRange:range withString:string];
        //正则检测
        NSString *stringRegex = @"(([0]|(0[.]\\d{0,2}))|([1-9]\\d{0,7}(([.]\\d{0,2})?)))?";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", stringRegex];
        if ([predicate evaluateWithObject:toString]) {
            return YES;
        }
        return NO;
    }
    

    相关文章

      网友评论

          本文标题:iOS中的正则表达式

          本文链接:https://www.haomeiwen.com/subject/shettqtx.html