其他分享
首页 > 其他分享> > 无痛的正则表达式,今天学完,明天找工作(上)

无痛的正则表达式,今天学完,明天找工作(上)

作者:互联网

家是否和我一样,学正则表达式不得要领,常学常忘,常忘常学,沉(tong)迷(ku)到无法自拔。

后来,我做了很多实际项目,才发现了正则的学习门道。本号将多年武功内力浓缩成两篇秘籍,可以无痛、快捷地掌握正则要义。上篇,我总结了7个要点,几乎可以解决99%的正则问题。下篇我会讲解正则表达式剩余知识点,并进行完整总结。

目录

一、问题引入

1.实际问题

2.推荐3个网站

3.复制电话到站长工具,使用正则表达式  1[0-9]{10}  即可提取所有电话 

二、正则要点

1:普通字符,直接写

2:一批字符,方括号[]

3:重复次数,花括号{}

4:或者选择,1竖线|

5:一组字符,圆括号()

6:反向引用,斜杠数\

7:零宽断言,等不等?=   ?!    ?<=    ?

三、动手练习

一、问题引入
1.实际问题
有某网友在下班前半小时接到老板要求,提取1万多个商铺的手机(电子表格见下图),商铺座机、商铺400客服电话都不要。假若是你接到任务,可以在多长时间内完成老板任务,能按时下班吗?

2.推荐3个网站
测试正则网站  http://tool.chinaz.com/regex(速度快,功能够用)或者https://regex101.com/(速度慢,功能全),二选一即可。

正则图解网站  https://regexper.com/

3.使用正则一键提取 
复制电话到站长工具,使用正则表达式  1[0-9]{10}  即可提取所有电话

正则表达式功能强大,接下来将以电话提取为题目,通过7个要点学习如何通过正则提取电话。

二、正则要点
1.普通字符,直接写
上图中正则表达式1[0-9]{10},其中1是普通字符,表示所有手机都是1打头。

如果老板要找上海的6打头的座机,可以写021-6[0-9]{7},其中021-6就是普通字符,直接写。

如果老板要找上海的6打头且末位是8的座机,冰雪聪明的读者,你现在能写吗?

2.一批字符,方括号[]
手机号码是1打头,后面的数字是0到9之中任意一个数。正则表达式规定方括号可以写出所有情况,如:[0123456789]或者[1357902468]等等,表明方括号处的符号是0到9之中某一个。

如果是小写字母,可以这样[abcdefghijklmnopqrstuvwxyz]或者[qwertyuiopasdfghjklzxcvbnm]。

但是这样写太复杂,可以简化写法[0-9],[a-z]。注意,不可以[9-0]或者[z-a]。why?不要问我,问美国标准化信息协会,他们规定数字最小的是0最大的是9,小写字母最小的是a最大的是z,具体见ASCII代码表。

3.重复次数,花括号{}
手机号码共11位,1打头,后面10位都是数字,方括号[0-9]可以表明任意一个数字。接下来,就可以笨笨地写出正则表达式:1[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]。

正则如此聪明,上述笨写法当然可以简化,用花括号就可以表明重复多少次,手机号码可以简写成:1[0-9]{10}。{10}表明前面的数字[0-9]必须重复10次。

假设,只是假设,我们手机号是9-11位的,那么正则可以简写成:1[0-9]{8,10}。假设我们手机号码最少9位,最多多少位不确定,那么正则可以简写成:1[0-9]{8,}。

4.或者选择,1竖线|
假设老板要大家找出武汉和上海的座机电话,大家该怎么办?可以分两次用正则找,然后复制出来粘贴到一起交差。如:先找上海座机021-[0-9]{8},然后找武汉座机027-[0-9]{8}。

聪明的大家可能想到方括号,可以一次性查找两地电话。这里我不炒现饭,不用方括号的解法,介绍一个新的正则功能“或者”。

通过或者|,可以简化成1次进行查找,或者符号是1条竖线|,正则表达式:021-[0-9]{8}|027-[0-9]{8}。

5.一组字符,圆括号()
数学中通过括号可以提取公因式,如:ma+mb+mc=m(a+b+c)。

上例中一次提取上海和武汉座机,就可以通过圆括号进行进一步简化,-[0-9]{8}可以提取出来,如:(027|021)-[0-9]{8},或者02(7|1)-[0-9]{8}。

圆括号是分组的意思,通过分组,让或者的范围从整个表达式缩小到分组这样的一个小局部。下图在regexper.com中分3次绘制。

6.反向引用,斜杠数\
回文是有趣的文字现象,如:上海自来水来自海上。座机电话号码也可以有回文形式,如:021-87655678。由于回文给出的规律是第1个数和第8个数相同,第2个数和第7个数相同,第3个数和第6个数相同,第4个数和第5个数相同,这样正则就必须表达第几个数。正则用分组和反向引用来解决这个问题。

首先,电话号码的前4个数字进行分组,正则表达式:([0-9])([0-9])([0-9])([0-9])。

然后,这4个分组叫1号分组,2号分组,3号分组,4号分组,分别用反斜杠数字表达,如:\1,\2,\3,\4。

最后,回文的正则表达为:([0-9])([0-9])([0-9])([0-9])\4\3\2\1。

7.零宽断言,等不等?=   ?!    ?<=    ?<!
在回文电话中,意外抓取到了手机号码中的回文,如果老板要求回文座机号码,正则可以解决吗?

我们的例子中,座机号码和手机号码的区别是 座机号码有一个横线,那么回文座机号码就有了一个要求,回文必须前面有一个横线,而横线不要进行正则匹配。那么零宽断言就可以解决,正则表达式:(?<=-)([0-9])([0-9])([0-9])([0-9])\4\3\2\1,可以匹配座机电话中的回文。

(?<=-)叫零宽度正回顾后发断言,表明横线-必须出现,但是匹配结果中不出现横线-。

如果不要前面出现横线,可以使用零宽度负回顾后发断言(?<!-),会匹配非座机中的回文,正则表达式:(?<!-)([0-9])([0-9])([0-9])([0-9])\4\3\2\1。

可以使用零宽度正回顾先发断言(?=-),会匹配回文后面有横线的回文,正则表达式:([0-9])([0-9])([0-9])([0-9])\4\3\2\1(?=-)。

可以使用零宽度负回顾先发断言(?!-),会匹配回文后面有横线的回文,正则表达式:([0-9])([0-9])([0-9])([0-9])\4\3\2\1(?!-)。

三、动手练习
到此,已经学完正则7个要点,几乎可以解决正则99%的问题。光说不练假把式,小试牛刀一下吧:

题目1: 前后都是空格的6位数字的邮编,不匹配空格只匹配6位数字。

题目2:小时分钟秒,形如HH:MM:SS。小时HH是00-23,必须2位数。分钟MM是00-59,必须2位数。秒SS是00-59,必须2位数。

题目3:年月日,形如YYYY-MM-DD或者YYYY/MM/DD。年YYYY是1000到2999。月是1到12或01到12,可以1位数,也可以2位数。日是1到31或01到31,可以1位数,也可以2位数,不要求分析大月小月。注意前后分隔符必须统一,不允许YYYY-MM/DD或者YYYY/MM-DD。

附录(练习用电话号码,都已被我修改过,不是真实电话。):

18121259651

021-54251306

027-64337018

020-54272788

021-33687788/18621164392

13124885895

021-54566545

18285522558

15807697545

021-54277790

13166257711

021-52835890

021-62099872

021-68321717

17802169959

4008988777

021-62780757

027-62341717

021-60318297

020-62155310

027-62771517

020-62459535

027-62270156

13918766200

021-52801923

021-62810973

18075106991/021-62645263

021-61169555

021-52806899

021-62091717

021-62152777

021-62365907

关注“关山号 ” (guanshan-hao),欢迎留言提问吐槽!

————————————————
版权声明:本文为CSDN博主「testcqw」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cqwygg/article/details/106893222

标签:10,正则表达式,可以,正则,021,无痛,学完,回文
来源: https://blog.csdn.net/qq_45272642/article/details/121096918