正则表达式在工作中的应用

一个复杂的正则表达式

写在前面

  正则表达式是字符串匹配、替换和提取时经常用到的一种技术,但由于它的语法晦涩(尤其像上面对比较复杂的场景时),初学者不容易读,更不容易写,所以并不是所有人都熟悉它的用法。现在网络上已经有很多正则表达式的教程了,这里不打算照抄一遍,而是换一个角度,从实用的场景出发,来介绍正则表达式的用法。

  为什么这样学呢?这就好像我们学语言一样,如果拿着一本字典去学,可能几天就放弃了,因为语法是枯燥的,而且可能只有20%的内容经常使用,剩下80%的内容极少使用,我们如果一上来就从头到尾顺序地学习语法,坚持下来很难,也很容易学过就忘了,最后白白浪费时间,通过场景的学习,更容易让人联系到平时的工作之中,更容易产生大脑的连接,从而印象更深刻。相信通过这些场景的学习,你会对正则表达式有一个新的认识,它不但是某些场景的必备,还是你平时工作提效的利器!

  下面的三个场景,分别是匹配、替换、提取。匹配是最常用的,判断一下输入的内容是不是手机号,这就是个匹配,替换使用的略少,一般在文本编译器中,我们想把一个内容,替换为另一个内容,用的就是替换。提取相对来说用的就是特定场景了,经常在网络爬虫中使用,在一篇文章中,找到所有的超链接。

  接下来开始我们的学习。

字符串匹配

  你是否还记得,当注册一个网站时,会让你使用一个邮箱,来确定你的真实性,然后往邮箱里发个验证码,如何证明你输入字符串符号邮箱的规则呢?这里用到的就是正则表达式匹配。

  1. 邮箱匹配

  例如我们常用的邮箱有以下几种(如果你是这个用户系统的开发者,支持的邮箱可能会更多):

邮箱类型 邮箱示例
网易邮箱 learnregex@163.com
QQ邮箱 123456@qq.com
新浪邮箱 learnregex123@sina.cn
谷歌邮箱 learnregex_abc@gmail.com

  首先观察,每个邮箱都有个@符号,第一个网易163邮箱,比较简单,@前面都是英文字母,@后面是3个数字,加一个.com:
邮箱组成分析

  因此我们可以写为:[a-z]{10}@[1-9]{3}\.com
在这里插入图片描述
我们拆开来看,第一部分是@前面的,[a-z]{10},什么意思呢?[a-z]表示范围,即a直到z之间的字母,{10}表示有10个字母。其中,方括号和大括号在正则中有特殊的含义:

字符的集合:[abcd]。表示的就是abcd任意字母出现都会匹配到
字符集合的反集合,即不包含指定字符集合:[^abcd]。表示的是只匹配不包含abcd的字符
字符的范围集合:[a-z]。表示的只要是a到z之间的字符都会匹配。
字符范围集合的反集合,即不包含指定字符范围的反集合:[^a-g]。表示只匹配a-g之外的那些集合
同样的,如果方括号中不是字母,而是数字,也是同样的道理,例如[0-9]表示的就是匹配0到9的数字。

表示匹配的次数:{10}表示精确匹配10次
表示匹配最少次数:{1,}表示至少匹配1次,多了不限制
表示匹配最多次数:{,10}表示最多匹配10次,少了不限制
表示匹配次数范围:{1,10}表示匹配1到10次。

@之后呢,[0-9]{3}表示有3个数字,[0-9]还是表示数字范围,{3}表示匹配的次数,.com中的.为什么用.来表示呢?因为.在正则中有特殊的含义,因此前面要加一个\用来转义。
我们可以找一个在线正则验证工具试一下。
正则表达式测试
  除了.之外还有别的需要转义吗?事实上在正则表达式中有特殊含义的词,如果想匹配都要转义。例如.、[、{、?…

  以上[a-z]{10}@[1-9]{3}\.com能匹配 learnregex@163.com 了,但是如果前缀和后缀换了呢?肯定就匹配不上了,因此我们要把精确匹配换成范围匹配,我们假设前缀的长度必须大于1,小于100,可以包含数字、字母和下划线,后缀也可以是字母和数字,没有下划线,长度是1到10个,同时域名除了.com还可能是.cn,我们看看这个正则怎么写[a-z0-9_]{1,100}@[a-z0-9]{1,10}\.[a-z]{1,3}

  我们再来测试一下
邮箱正则表达式

  1. 手机号匹配

  现在早已是移动互联网时代,在App注册时,经常是通过手机验证码来验伪的,如何判断一个字符串是一个手机号呢?手机号相比邮箱相对简单,只有数字,但数字是有规则的,并不是任何一个11个数字的集合就是手机号,例如1231231231就不是一个有效的手机号。同样我们在互联网上找一下手机号的相关组成规则:

我国使用的号码为11位,其中各段有不同的编码方向:第1-3位—网络识别号;第4-7位—地区编码;第8-11位—用户号码。

运营商 号段
中国电信 133、149、153、173、177、180、181、189、190、191、193、199
中国联通 130、131、132、145、155、156、166、167、171、175、176、185、186、196
中国移动 134(0-8)、135、136、137、138、139、1440、147、148、150、151、152、157、158、159、172、178、182、183、184、187、188、195 [1] 、197、198
中国广电号段 192

参考 :百度百科-手机号码

  根据以上的资料,我们分析下手机号的组织规则,知道了组织规则后,写正则就不麻烦了。

  • 第1位:永远是1
  • 第2位:3~9
  • 第3位:0~9
  • 后续位:不限制
      因此我们的正则可以写为:1[3-9][0-9][\d]{8},接下来验证一下是否正确。
    手机号正则
      上面的正则对输入格式限制的很宽泛,我们经常还会看到一些做法是,将号码段进行穷举,例如:(133|149|153|173)[\d]{8}
    在这里插入图片描述
      需要指出的是,虽然上面这种穷举的方式更为准确,但也有一定的缺点,一是比较难维护,模式串比较长;二是不知道什么时候出现新的手机号码段时,系统就会提示错误,给用户不好的体验。因此还是建议不要用穷举的方式去做手机号验证。
  1. 身份证号匹配
      与前面的步骤一样,我们先看一下我国关于身份证号码相关的资料。
    公民身份证号码规则
      如上图所示,我国公民身份证号码,由18位组成(之前是15位),前6位为地区编码,分别为省市区,然后跟着8位是出生年月日,再跟着3位是顺序号,最后一位为验证码,校验码之前的10位,都是0-9的数字,最后一位不同,是验证码,值为0-9或者为x。
      因此我们可以简单写正则为\d{17}[\d|X]{1}
    身份证号正则

参考:
公民身份号码
2020年11月中华人民共和国县以上行政区划代码

字符串替换

  其实学会验证,再替换就不困难了,但是替换的场景其实很多,如果能灵活的使用的替换,可以在工作中产生事半功倍的效果。

Java代码中的字符串替换

String类的replaceAll方法,使用的就是正则匹配加替换的

public String replaceAll(String regex, String replacement) {
   
    return Pattern.compile(regex).matcher(this).replaceAll(replacement);
}

  于是,我们可以该方法来替换。比如公司安全部门经常要对日志进行扫描,防止程序员将手机号等敏感信息打到日志中,我们写个测试方法,将字符串中的手机号替换为***

    public static void testReplaceAll(){
   
        String text = "今天工作中,我向客户张三要到了手机号15212123430,向客户李四要到了手机号13923210384,同时和他们建立一定的合作意向";
        String pattern = "1[3-9][0-9][\\d]{8}";
        System.out.println(text.replaceAll(pattern,"***"));
    }

输出:

今天工作中,我向客户张三要到了手机号***,向客户李四要到了手机号***,同时和他们建立一定的合作意向

在idea中替换

  在项目重构过程中,经常会遇到将某些类定义进行修改的情况,例如将某个类的所有类型为String字段都加上一个注解,如果打开每个Java类对一行一行的添加,类文件少的时候还可以,一旦非常多,如几十个甚至上百个,这个工作量就不小了,这时我们就可以通过正则替换的方式来做,只需要简单几步就能完成小白一天的工作量。
示例:

public class UserInfo {
   
    private String name;
    private Integer age;
    private String address;
    private Date birthday;
    private String country;
    private String cityCode;
    private String device;
    private Double high;
    private Double height;
}

  现在我们在每个字段上,加上@Getter注解,如下,我们只替换UserInfo.java这个文件,使用(private.*;)筛选所有以private开头的字段,替换为@Getter注解\n$1\n,其中$1是提取的上面正则括号中内容,也即每个字段的行。

  替换框使用快捷键cmd+shift+F,替换时选择正则,.图标表示正则。
如果我们有100个类文件,只需要选中相应的文件,如
Entity.java选中所有的实体类,即可一键替换。
在Idea中使用正则替换

内容提取

  内容提取,在写网络爬虫时使用最为广泛,例如我们下载下https://www.hao123.com/的页面,然后提取其中所有的<a>标签。
内容:

<div class="user-common-sites" id="userCommonSites"><div class="js_manage site-manage" title="添加网址"></div><ul class="js_bd cls_bd"><li class="js_site-item site-item" data-id="1" data-title="百度" data-icon="https://dgss0.bdstatic.com/5bVWsj_p_tVS5dKfpU_Y_D3/res/r/image/2021-3-5/baidulogo.png" data-status="1" title="百度"><div class="inline-block-wrapper"><a class="sitelink icon-site" href="http://www.baidu.com/?tn=sitehao123_15" style="background-image: url(https://dgss0.bdstatic.com/5bVWsj_p_tVS5dKfpU_Y_D3/res/r/image/2021-3-5/baidulogo.png)" data-title="百度">百度</a></div></li><li class="js_site-item site-item" data-id="2" data-title="新浪" data-icon="https://dgss0.bdstatic.com/5bVWsj_p_tVS5dKfpU_Y_D3/qiusuo_icon/10597f220b047cee3e8ea50e91886d71.ico" data-status="1" title="新浪"><div class="inline-block-wrapper"><a class="sitelink icon-site main-site" href="http://www.sina.com.cn/" style="background-image: url(https://dgss0.bdstatic.com/5bVWsj_p_tVS5dKfpU_Y_D3/qiusuo_icon/10597f220b047cee3e8ea50e91886d71.ico)" data-title="新浪">新浪</a><a class="sitelink sub-site" href="https://weibo.com/" data-title="微博">微博</a></div></li><li class="js_site-item site-item" data-id="3" data-title="搜狐" data-icon="https://dgss1.bdstatic.com/5bVXsj_p_tVS5dKfpU_Y_D3/data/8d6d2c708fbf92d23e3852340d72f9ff" data-status="1" title="搜狐"><div class="inline-block-wrapper"><a class="sitelink icon-site main-site" href="http://www.sohu.com/" style="background-image: url(https://dgss1.bdstatic.com/5bVXsj_p_tVS5dKfpU_Y_D3/data/8d6d2c708fbf92d23e3852340d72f9ff)" data-title="搜狐">搜狐</a><a class="sitelink sub-site" href="http://tuijian.hao123.com/" data-title="热点">热点</a></div></li><li class="js_site-item site-item" data-id="4" data-title="腾讯" data-icon="https://dgss2.bdstatic.com/5bVYsj_p_tVS5dKfpU_Y_D3/qiusuo_icon/5838ed1d6a3eef9f91341d9a8af16db8.ico" data-status="1" title="腾讯"><div class="inline-block-wrapper"><a class="sitelink icon-site" href="http://www.qq.com/" style="background-image: url(https://dgss2.bdstatic.com/5bVYsj_p_tVS5dKfpU_Y_D3/qiusuo_icon/5838ed1d6a3eef9f91341d9a8af16db8.ico)" data-title=
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值