美文网首页
正则表达不再靠control+v(实操篇)

正则表达不再靠control+v(实操篇)

作者: HotCatLx | 来源:发表于2018-05-11 11:32 被阅读12次

    1. 前言

    • 前面的正则的基础语法了解之后,正式开始实际应用
    • 对基础知识感兴趣的可以看看我写的基础篇 《正则表达不再control+v》
    • 结尾有一些常用的正则表达式,但是想了解为什么还是最好顺序阅读
      awesome.JPG

    2.子表达式

    2.1 概念

    • ()括起来的就是子表达式
    • 我的理解:子表达式的目的是为了增加匹配的优先级,子表达式内的优先级较高,优先匹配
    • 子表达式可以嵌套,这个在下面会通过例子来解释

    2.2 实战-IP地址的匹配

    • 我们会一步一步完善和简化一个IP的正则表达式

    • 需求分析:IP 地址是由.分隔的四组数字,如192.168.1.106。因为每个部分的数字都可以为1-3位数字字符

      IP地址匹配1.0.png
    • 分析

      first:\d{1,3}表示匹配一个由数字组成的1-3位的字符串
      second:\d{1,3}\.表示1-3位数字,并以.结尾
      third:最后一组字符串不需要以.结尾,所以\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}貌似可以解决IP的匹配

    • 但是d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}这个正则,重复表达式太多,垃圾代码那么多能忍么???那么子表达式就出现用处了

      IP地址匹配1.0-子表达式简化版.png
    • 分析

      \d{1,3}\.()子表达式括起来,并加上重复执行次数,能简化正则的可阅读性

    • 那么我们的IP正则的容错性到底怎么样?


      IP地址匹配-非法IP校验.png
    • 非法IP也能被匹配,说明我们的IP匹配有问题,其实是需求分析有问题,IP的地址规则并未完全体现,那么补充需求之后再完善我们的IP地址匹配吧

    IP地址规则:

    1. 所有的一位数和两位数
    2. 三位数的第一位为 1
    3. 如果三位数的第一位为 2 ,且第二位从 0 到 4
    4. 如果三位数的前二位为 25 ,且第三位从 0 到 5
    5. 总结:0-255.0-255.0-255.0-255 就是我们要写的
    • 明确了规则,把每条规则实现即可


      IP地址匹配2.0.png
    • 新的实现(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5])),一个匹配里嵌套了四组子表达式

    解析:
    1.将整个正则拆成两个部分((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5])),前一部分重复三次用来表示前面三组数字,并且以.结尾,后一部分表示最后一组IP地址
    2.第一部分:(\d{1,2}),这个子表达式将匹配一位或者两位任意数字
    3.第二部分:((1\d{2}),这个子表达式将匹配以1开头的后两位任意数字的三位数字
    4.第三部分:(2[0-4]\d),这个子表达式将匹配以2开头的中间一位为0-4,第三位为任意数字的字符串
    5.第四部分:(25[0-5]),这个子表达式将匹配以25开头的尾数为0-5的三位数字

    • 还有网上很多别的写法,但是我觉得这个写法是比较好理解的版本,所以如果有更好的,可以告诉我,毕竟我觉得真的很长

    2.3 年份匹配

    • 这个需求很简单,就是匹配19xx-20xx所有年份
    • 目的:体验子表达式的优先级
    • 实用性:我觉得这种简单的正则在开发中实用性很强,很多都可以用到
      年份匹配-错误版本.png
    • 解释

    1.19|20\d{2}这个表达式没有达到我们的效果
    2.这个表达式其实的效果是匹配19(两位)和以20开头的四位数字
    3.这里就能体现子表达式的效果,我们想要的是19或者20开头的四位数字,那么我们完全可以这部分用子表达式括起来,来实现效果

    年份匹配-正确版本.png

    2.4 HTML标签匹配

    • 需求:匹配H5标签,因为H5标签的格式还是很固定的<xxx>xxx</xxx>
    • 知识点:这里会用到向后引用这个写法
    • 以匹配H标签为例


      标签匹配-错误版.png
    • 这里就有个需求就是前面和后面的相同匹配规则匹配保持一致,比如前面匹配了H2标签,后面还是要匹配H2标签,前后一致

    2.4.1 后向引用

    • 后向引用就是引用前面的子表达式
    • 使用小括号指定一个子表达式后,匹配这个子表达式的文本(也就是此分组捕获的内容)可以在表达式或其他程序中作进一步处理。默认情况下,每个分组会自动拥有一个组号,规则是:从左向右,以分组的左括号为标志,第一个出现的分组的组号为1,第二个为2,以此类推
    • 后向引用用于重复搜索前面某个分组匹配的文本
    • 可以参考文章: 正则表达式后向引用~~~~~~ & 正则表达式后向引用

    2.4.2 HTML标签匹配之向后引用

    • 但是我这里遇到了个问题:使用Regextor出现了不能匹配正确的向后引用,我不确定是APP不能识别这种语法还是什么原因,如果有知道请告诉我
      Regextor不支持向后引用么?.png
    • 我们在xcode中使用了匹配查询,这个正则完全能达到我们的要求


      xcode匹配结果.png
    • <[hH]([1-5])>.*?</[hH]\1>分析

    <[hH]([1-5])>中将第一个子表达式使用()括起来,在缓存中使用这个子表达式默认为第一个分组
    </[hH]\1>\1使用第一个的子表达式的匹配取值应用到第二处,不如前面匹配了1,后面只能匹配1

    3,实际开发应用

    3.1 查找替换文本

    • 2.4.2 HTML标签的匹配中就用xcode的查找操作


      xcode匹配.png

    3.2 校验字符串是否符合规则-NSPredicate

    • 最常用的一种方式
    NSString *string = @"hotCat";
    //正则
    NSString *regex = @"^ho[a-zA-Z]{2,}*$";
    //创建NSPredicate
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    BOOL result = [predicate evaluateWithObject:string];
    

    3.3 字符串某一个字符或者字符集的定位

    • 用处:特定的字符串的替换,或者某些字符的删除,都可以使用,因为可以拿到想要的NSRange
    NSString *string = @"hotCat123";
    //使用正则\d+去string中进行匹配,得到的时匹配到的range,在这里为{4,3}。
    NSRange range = [string rangeOfString:@"\\d+" options:NSRegularExpressionSearch];
    //如果匹配到就打印匹配到的子字符串,在这里为123。
    if (range.location != NSNotFound)
    {
        NSLog(@"%@",[string substringWithRange:range]);
    }
    
    

    分析:
    1.\d+用来查找数字
    2.rangeOfString:options:会返回一个NSRange,用来接收匹配的范围options必须要用NSRegularExpressionSearch,代表用正则去匹配
    3.当写正则字符串时,\需要写成\\ ,所以,\d+需要写成\\d+

    3.4 NSRegularExpression

    • NSRegularExpression这个类可以用户来查找字符串中符合要求的第一个匹配结果或者所有匹配结果
    • 这个使用很简单,就不详细介绍了,如果有想知道使用的,可以移步oc中正则表达式NSRegularExpression类详解

    3.5 其它

    • 我觉得还可以有很多高级的用处,但是实际开发中还没遇到,如果有遇到可以告诉我,我会去在深入学习下,谢谢啦!!!

    4. 最后的福利

    • 最后的留一些常用的校验吧,以免有人偷懒,所以写在最后,但是可能不知道是否符合最新的标准,比如手机号码,新字段开发太快了
    /**
         * 手机号码:
         * 13[0-9], 14[5,7], 15[0, 1, 2, 3, 5, 6, 7, 8, 9], 17[0, 1, 6, 7, 8], 18[0-9]
         * 移动号段: 134,135,136,137,138,139,147,150,151,152,157,158,159,170,178,182,183,184,187,188
         * 联通号段: 130,131,132,145,155,156,170,171,175,176,185,186
         * 电信号段: 133,149,153,170,173,177,180,181,189
         */
        NSString *MOBILE = @"^1(3[0-9]|4[57]|5[0-35-9]|7[0135678]|8[0-9])\\d{8}$";
        /**
         * 中国移动:China Mobile
         * 134,135,136,137,138,139,147,150,151,152,157,158,159,170,178,182,183,184,187,188
         */
        NSString *CM = @"^1(3[4-9]|4[7]|5[0-27-9]|7[08]|8[2-478])\\d{8}$";
        /**
         * 中国联通:China Unicom
         * 130,131,132,145,155,156,170,171,175,176,185,186
         */
        NSString *CU = @"^1(3[0-2]|4[5]|5[56]|7[0156]|8[56])\\d{8}$";
        /**
         * 中国电信:China Telecom
         * 133,149,153,170,173,177,180,181,189
         */
        NSString *CT = @"^1(3[3]|4[9]|53|7[037]|8[019])\\d{8}$";
    
    
    邮箱:   ^[a-zA-Z0-9]{4,}@[a-z0-9A-Z]{2,}\\.[a-zA-Z]{2,}$
    大陆固定电话号码:    ^\\d{4}-|\\d{3}-)?(\\d{8}|\\d{7}$
    身份证号:    \\d{14}[[0-9],0-9xX]
    Email地址:    ^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\.\\w+([-.]\\w+)*$
    纯数字:   ^[0-9]*$
    由数字和英文字母组成:   ^[A-Za-z0-9]+$
    QQ号:   ^[1-9][0-9]\{4,\}$
    中国邮政编码:   ^[1-9]\\d{5}(?!\\d)$
    URL:  ^http(s)?://([\\w-]+\\.)+[\\w-]+(/[\\w- ./?%&=]*)?$
    纯汉字中文:^[\u4e00-\u9fa5]{0,}$
    
    
    Thanks.JPG

    相关文章

      网友评论

          本文标题:正则表达不再靠control+v(实操篇)

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