打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
20分钟内看完这篇,闭着眼写正则表达式
userphoto

2022.05.11 陕西省

关注

正则表达式极速入门

  • 开篇词:
    • 1.正则是什么,能做什么?
    • 2.如何学习和使用正则的?
  • 基础篇:
    • 1.如何巧妙记忆正则表达式的基本元件?
    • 2.小小的正则,也可能把CPU拖垮!
    • 3.一次性掌握正则中常见的4种匹配模式
  • 应用篇:
    • 1.如何用断言更好地实现替换重复出现的单词?
    • 2.正则中转义需要注意哪些问题?
    • 3.正则有哪些常见的流派及其特性?
    • 4.正则如何处理Unicode编码的文本?
    • 5.如何用正则让文本处理能力上一个台阶?
    • 6.如何理解正则的匹配原理以及优化原则?
    • 7.详解正则常见问题及解决方案
  • 结束语:
    • 1.如何检验自己的掌握程度
    • 2.熟练运用,而不滥用
    • 3.如何进一步成长?
  • 我是杰叔叔,一名沪漂的码农,下期再会!

开篇词:

我相信,作为一名程序员或者准程序员,你肯定是知道正则表达式的。但实际开发中,真正去手写一个满足需求校验的正则,往往磕磕绊绊,最后都是去 Google 搜一搜,然后复制过来改一改。
此时大多数程序员心里可能是这么想的:我在工作中用到正则的时候并不多啊,要用的时候搜一下就好了啊,为什么还要专门花时间和精力学它呢?
大概会存在如下几点困惑:

  • 学过正则,但觉得过于复杂,根本记不住;
  • 在网上找到的正则和自己的需求有一点出入,不知道该怎么改;
  • 不清楚正则的流派和支持情况,搞不懂为何自己写的正则没达到效果;
  • 不清楚正则的工作原理,容易出现性能问题

1.正则是什么,能做什么?

正则,就是正则表达式,英文是 Regular Expression,简称 RE。顾名思
义,正则其实就是一种描述文本内容组成规律的表示方式。
在编程语言中,常用的使用场景

  • 利用它来校验数据的有效性,比如用户输入的手机号是不是符合规则
  • 可以从文本中提取想要的内容,比如从网页中抽取数据
  • 还可以用来做文本内容替换,从而得到我们想要的内容

2.如何学习和使用正则的?

对于正则表达式,我们有没有可能“打出⼀⼝永不⼲涸的深井”呢?
当然有,那就是⼀次性多投⼊点时间,由表及里,由术及道

第⼀步,做分解。

拿到一个问题后,我们要先思考:这个问题可以分为⼏个⼦问题?每个⼦问题是否独⽴?我们拿最常⻅的电⼦邮件地址匹配来说。从文本结构来看,它可以分为“username + @ + domain name”这三个独⽴的部分。怎么画呢?我们可以先画出逻辑结构图。通过这个过程来厘清思路。

第⼆步,分析各个⼦问题。

某个位置上可能有多个字符?那就⽤字符组。某个位置上可能有多个字符串?那就⽤多选结构。出现的次数不确定?那就⽤量词。对出现的位置有要求?那就⽤锚点锁定位置……
只要熟练掌握了,知道什么时候用字符组,什么时候用多选结构,什么时候用量词,什么时候用锚点,就很容易搭建起完整的概念模型。

第三步,套⽪。

正则中真正重要的是字符组、多选结构、量词等等这些概念。一旦你的概念模型清楚了,写出正则表达式就非常简单了,无非是查阅语法⼿册,把之前得到的概念模型按照对应语⾔或⼯具的约定写下来而已。虽然各种语⾔或⼯具对正则表达式的⽀持⼤同⼩异,但细微差别仍然不可忽视。

第四步,调试。

正则表达式的麻烦之处在于它像个⿊箱⼦,很难调适,只能笼统地知道“匹配了”或者“没匹配”。那到底怎么调试呢?我的经验是,复杂⼀点的正则表达式不能⼀次写对,这是很正常的。与其纠结“这个正则表达式看起来这么复杂,此处到底要用星号 * 还是加号 +,不如先搞清楚,星号( * )或加号( + )限定的到底是正则表达式中的哪一部分,对应要匹配文本中的哪一部分。这两个问题搞清楚了,整个问题就迎刃而解了

第五步伐,务必要保持克制 。

  • 能⽤普通字符串处理的,坚决⽤普通字符串处理。

  • 能写注释的正则表达式,⼀定要写注释。

  • 能⽤多个简单正则表达式解决的,⼀定不要苛求⽤⼀个复杂的正则表达式。

基础篇:

1.如何巧妙记忆正则表达式的基本元件?

首先,我可以把元字符大致分成这几类:

  • 特殊单字符
  • 空白符
  • 范围
  • 量词
  • 断言

1. 特殊单字符

英文的点(.)表示换行以外的任意单个字符,\d 表示任意单个数字,\w 表示任意单个数字或字母或下划线,\s 表示任意单个空白符。另外,还有与之对应的三个 \D、\W 和 \S,分别表示着和原来相反的意思。

2. 空白符

不同的系统在每行文本结束位置默认的“换行”会有区别。比如在 Windows 里是 \r\n,在 Linux 和 MacOS 中是 \n。在正则中,也是类似于 \n 或 \r 等方式来表示空白符号,只要记住它们就行了。平时使用正则,大部分场景使用 \s 就可以满足需求,\s 代表任意单个空白符号。

3. 量词

在正则中,英文的星号(*)代表出现 0 到多次,加号(+)代表 1 到多次,问号(?)代表 0 到 1 次,{m,n}代表 m 到 n 次。

4. 范围

在正则表达式中,表示范围的符号有四个分类,如下图所示。

比如 ab|bc 能匹配上 ab,也能匹配上 bc。
中括号[]代表多选一,可以表示里面的任意单个字符,所以任意元音字母可以用 [aeiou] 来表示。另外,中括号中,我们还可以用中划线表示范围,比如 [a-z] 可以表示所有小写字母。如果中括号第一个是脱字符(^),那么就表示非,表达的是不能是里面的任何单个元素。比如某个资源可能以 http:// 开头,或者 https:// 开头,也可能以 ftp:// 开头,那么资源的协议部分,我们可以使用 (https?|ftp)😕/ 来表示。

2.小小的正则,也可能把CPU拖垮!

正则中的三种模式,贪婪匹配、非贪婪匹配和独占模式。

1.贪婪匹配

在正则中,表示次数的量词默认是贪婪的,在贪婪模式下,会尝试尽可能最大长度去匹配。
例子:
首先,我们来看一下在字符串 aaabb 中使用正则 a* 的匹配过程


a* 在匹配开头的 a 时,会尝试尽量匹配更多的 a,直到第一个字母 b 不满足要求为止,匹配上三个 a,后面每次匹配时都得到了空字符串。

2.非贪婪匹配

我们可以在量词后面加上英文的问号 (?),正则就变成了 a*?。非贪婪模式会尽可能短地去匹配,我把这两者之间的区别写到了下
面这张图中。

3.独占模式

独占模式,它类似贪婪匹配,但匹配过程不会发生回溯,因此性能会更好。那什么是回溯呢?
举个例子:


在匹配时,y{1,3}会尽可能长地去匹配,当匹配完 xyy 后,由于 y 要尽可能匹配最长,即三
个,但字符串中后面是个 z 就会导致匹配不上,这时候正则就会向前回溯,吐出当前字符
z,接着用正则中的 z 去匹配。

如果我们把这个正则改成非贪婪模式,
如下图:


由于 y{1,3}? 代表匹配 1 到 3 个 y,尽可能少地匹配。匹配上一个 y 之后,也就是在匹配上text 中的 xy 后,正则会使用 z 和 text 中的 xy 后面的 y 比较,发现正则 z 和 y 不匹配,这时正则就会向前回溯,重新查看 y 匹配两个的情况,匹配上正则中的 xyy,然后再用 z去匹配 text 中的 z,匹配成功。

了解了回溯,我们再看下独占模式。

独占模式和贪婪模式很像,独占模式会尽可能多地去匹配,如果匹配失败就结束,不会进行
回溯,这样的话就比较节省时间。具体的方法就是在量词后面加上加号(+)
如下图:

4.总结

正则中量词默认是贪婪匹配,如果想要进行非贪婪匹配需要在量词后面加上问号。贪婪和非贪婪匹配都可能会进行回溯,独占模式也是进行贪婪匹配,但不进行回溯,因此在一些场景下,可以提高匹配的效率,具体能不能用独占模式需要看使用的编程语言的类库的支持情况,以及独占模式能不能满足需求。

3.一次性掌握正则中常见的4种匹配模式

所谓匹配模式,指的是正则中一些改变元字符匹配行为的方式,比如匹配时不区分英文字母大小写。常见的匹配模式有 4 种,分别是不区分大小写模式、点号通配模式、多行模式和注释模式。

1.不区分大小写模式(Case-Insensitive)

当我们把模式修饰符放在整个正则前面时,就表示整个正则表达式都是不区分大小写的。
例子:不区分大小写的 cat 就可以写成 (?i)cat

如果我们想要前面匹配上的结果,和第二次重复时的大小写一致,那该怎么做呢?
只需要用括号把修饰符和正则 cat 部分括起来:
例子: ((?i)cat) \1

如果用正则匹配,实现部分区分大小写,另一部分不区分大小
写,这该如何操作呢?就比如说我现在想要,the cat 中的 the 不区分大小写,cat 区分大
小写。
例子: ((?i)the) cat

2.点号通配模式(Dot All)

英文的点(.)有什么用吗?它可以匹配上任何符号,但不能匹配换行。当我们需要匹配真正的“任意”符号的时
候,可以使用 [\s\S] 或 [\d\D] 或 [\w\W] 等。

3.多行模式

^ 匹配整个字符串的开头
$匹配整个字符串的结尾

4.注释模式

正则中注释模式是使用(?#comment) 来表示。
例子:(\w+)(?#word) \1(?#word重复一次)

5.总结

应用篇:

1.如何用断言更好地实现替换重复出现的单词?

什么是断言呢?简单来说,断言是指对匹配到的文本位置有要求。你应该知道 \d{11} 能匹配上 11 位数字,但这 11 位数字可能是 18 位身份证号中的一部分。再比如,去查找一个单词,我们要查找 tom,但其它的单词,比如 tomorrow 中也包含了 tom。也就是说,在有些情况下,我们对要匹配的文本的位置也有一定的要求。为了解决这个问题,正则中提供了一些结构,只用于匹配位置,而不是文本内容本身,这种结构就是断言。
常见的断言有三种:单词边界、行的开始或结束以及环视。


1.单词边界(Word Boundary)

在讲单词边界具体怎么使用前,我们先来看一下例子。我们想要把下面文本中的 tom 替换成 jerry。注意一下,在文本中出现了 tomorrow 这个单词,tomorrow 也是以 tom 开头的。
利用前面学到的知识,我们如果直接替换,会出现下面这种结果。


这显然是错误的,因为明天这个英语单词里面的 tom 也被替换了。那正则是如何解决这个问题的呢?单词的组成一般可以用元字符 \w+ 来表示,\w 包括了大小写字母、下划线和数字(即 [A-Za-z0-9_])。那如果我们能找出单词的边界,也就是当出现了\w 表示的范围以外的字符,比如引号、空格、标点、换行等这些符号,我们就可以在正则中使用\b 来表示单词的边界。 \b 中的 b 可以理解为是边界(Boundary)这个单词的首字母。

根据刚刚学到的内容,在准确匹配单词时,我们使用 \b\w+\b 就可以实现了。

2.行的开始或结束

和单词的边界类似,在正则中还有文本每行的开始和结束,如果我们要求匹配的内容要出现在一行文本开头或结尾,就可以使用 ^ 和 $ 来进行位置界定。我们先说一下行的结尾是如何判断的。你应该知道换行符号。在计算机中,回车(\r)和换行(\n)其实是两个概念,并且在不同的平台上,换行的表示也是不一样的。我在这里列出了 Windows、Linux、macOS 平台上换行的表示方式。


那你可能就会问了,匹配行的开始或结束有什么用呢?

3.日志起始行判断

最常见的例子就是日志收集,我们在收集日志的时候,通常可以指定日志行的开始规则,比如以时间开头,那些不是以时间开头的可能就是打印的堆栈信息。我来给你一个以日期开头,下面每一行都属于同一篇日志的例子


在这种情况下,我们就通过日期时间开头来判断哪一行是日志的第一行,在日期时间后面的日志都属于同一条日志。除非我们看见下一个日期时间的出现,才是下一条日志的开始。

4.输入数据校验

在 Web 服务中,我们常常需要对输入的内容进行校验,比如要求输入 6 位数字,我们可以使用 \d{6} 来校验。但你需要注意到,如果用户输入的是 6 位以上的数字呢?在这种情况下,如果不去要求用户录入的 6 位数字必须是行的开头或结尾,就算验证通过了,结果也可能不对。比如下面的示例,在不加行开始和结束符号时,用户输入了 7 位数字,也是能校验通过的:

5.环视( Look Around)

环视就是要求匹配部分的前面或后面要满足(或不满足)某种规则,有些地方也称环视为零宽断言。那具体什么时候我们会用到环视呢?我来举个例子。邮政编码的规则是第一位是 1-9,一共有 6 位数字组成。现在要求你写出一个正则,提取文本中的邮政编码。根据规则,我们很容易就可以写出邮编的组成 [1-9]\d{5}。我们可以使用下面的文本进行测试


我们发现,7 位数的前 6 位也能匹配上,12 位数匹配上了两次,这显然是不符合要求的也就是说,除了文本本身组成符合这 6 位数的规则外,这 6 位数左边或右边都不能是数字。正则是通过环视来解决这个问题的。解决这个问题的正则有四种。我给你总结了一个表。

你可能觉得名称比较难记住,没关系,我给你一个小口诀,你只要记住了它的功能和写法就行。这个小口诀你可以在心里默念几遍:左尖括号代表看左边,没有尖括号是看右边,感叹号是非的意思。因此,针对刚刚邮编的问题,就可以写成左边不是数字,右边也不是数字的 6 位数的正则。即 (?<!\d)[1-9]\d{5}(?!\d)。这样就能够符合要求了。

6.环视与子组

环视中虽然也有括号,但不会保存成子组。保存成子组的一般是匹配到的文本内容,后续用于替换等操作,而环视是表示对文本左右环境的要求,即环视只匹配位置,不匹配文本内容。你也可以总结一下,圆括号在正则中都有哪些用途,不断地去复习学过的内容,巩固自己的记忆。

7.总结

最常见的断言有三种:单词的边界、行的开始或结束、环视。单词的边界是使用 \b 来表示。而多行模式下,每一行的开始和结束是使用^ 和 $ 符号。如果想匹配整个字符串的开始或结束,可以使用 \A 和 \z,它们不受匹配模式的影响。最后就是环视,它又分为四种情况:肯定逆向环视、否定逆向环视、肯定顺序环视、否定顺序环视。在使用的时候记住一个方法:有左尖括号代表看左边,没有尖括号是看右边,而感叹号是非的意思。

2.正则中转义需要注意哪些问题?

1.转义字符

下面是一些常见的转义字符以及它们的含义。


2.字符串转义和正则转义

  • 一般来说,正则中 \d 代表的是单个数字,但如果我们想表示成 反斜杠和字母 d,这时候就需要进行转义,写成 \d,这个就表示反斜杠后面紧跟着一个字母 d
  • 刚刚的反斜杠和 d 是连续出现的两个字符,如果你想表示成反斜杠或 d,可以用管道符号或中括号来实现,比如 |d 或 [\d]。
  • 需要注意的是,如果你想用代码来测试这个,在程序中表示普通字符串的时候,我们如果要表示反斜杠,通常需要写成两个反斜杠,因为只写一个会被理解成“转义符号”,而不是反斜杠本身。
  • 那如何在正则中正确表示“反斜杠”呢?答案是写四个反斜杠。详细解释一下这里面的过程,在程序使用过程中,从输入的字符串到正则表达式,其实有两步转换过程,分别是字符串转义和正则转义。在正则中正确表示“反斜杠”具体的过程是这样子:我们输入的字符串,四个反斜杠 \,经过第一步字符串转义,它代表的含义是两个反斜杠 \;这两个反斜杠再经过第二步正则转义,它就可以代表单个反斜杠 \了

    你可以用这个过程,推导一下两个和三个反斜杠的转换过程,这样你就会明白上面报错的原因了。

3.正则中元字符的转义

如果现在我们要查找比如星号(*)、加号(+)、问号(?)本身,而不是元字符的功能,这时候就需要对其进行转义,直接在前面加上反斜杠就可以了。

4.括号的转义

在正则中方括号 [] 和 花括号 {} 只需转义开括号,但圆括号 () 两个都要转义。在正则中,圆括号通常用于分组,或者将某个部分看成一个整体,如果只转义开括号或闭括号,正则会认为少了另外一半,所以会报错。

5.使用函数消除元字符特殊含义

这个转义函数可以将整个文本转义,一般用于转义用户输入的内容,即把这些内容看成普通字符串去匹配,但你还是得好好注意一下,如果使用普通字符串查找能满足要求,就不要使用正则,因为它简单不容易出问题。下面是一些其他编程语言对应的转义函数,供你参考


6.字符组中的转义

讲完了元字符的转义,我们现在来看看字符组中的转义。书写正则的时候,在字符组中,如果有过多的转义会导致代码可读性差。在字符组里只有三种情况需要转义

  • 脱字符在中括号中,且在第一个位置需要转义:
  • 中划线在中括号中,且不在首尾位置:
  • 右括号在中括号中,且不在首位:

7.字符组中其它的元字符

  • 一般来说如果我们要想将元字符(.+?() 之类)表示成它字面上本来的意思,是需要对其进行转义的
  • 如果它们出现在字符组中括号里,可以不转义。这种情况,一般都是单个长度的元字符,比如点号(.)、星号()、加号(+)、问号(?)、左右圆括号等。它们都不再具有特殊含义,而是代表字符本身。
  • 如果在中括号中出现 \d 或 \w 等符号时,他们还是元字符本身的含义

8.总结

正则中转义有些情况下会比较复杂,从录入的字符串文本,到最终的正则表达式,经过了字
符串转义和正则转义两个步骤。元字符的转义一般在前面加反斜杠就行,方括号和花括号的
转义一般转义开括号就可以,但圆括号两个都需要转义,我们可以借助编程语言中的转义函
数来实现转义。另外我们也讲了字符组中三种需要转义的情况,详细的可以参考下面的脑
图。

3.正则有哪些常见的流派及其特性?

目前正则表达式主要有两大流派(Flavor):POSIX 流派与 PCRE 流派。下面我们分别来看看。

1.POSIX 流派

POSIX 规范定义了正则表达式的两种标准:

  • BRE 标准(Basic Regular Expression 基本正则表达式);
  • ERE 标准(Extended Regular Expression 扩展正则表达式)
    下图为两者间的区别:

2.PCRE 流派

除了 POSIX 标准外,还有一个 Perl 分支,也就是我们现在熟知的 PCRE。目前大部分常用编程语言都是源于 PCRE 标准,这个流派显著特征是有\d、\w、\s 这类字符组简记方式。


3.总结

4.正则如何处理Unicode编码的文本?

Unicode 基础知识

Unicode(中文:万国码、国际码、统一码、单一码)是计算机科学领域里的一项业界标准。它对世界上大部分的文字进行了整理、编码。现在的 Unicode 字符分为 17 组编排,每组为一个平面(Plane)而每个平面拥有65536(即 2 的 16 次方)个码值(Code Point)。然而,目前 Unicode 只用了少数平面,我们用到的绝大多数字符都属于第 0 号平面,即 BMP 平面。除了 BMP 平面之外,其它的平面都被称为补充平面。


Unicode 中的正则

5.如何用正则让文本处理能力上一个台阶?

我目前是从事java开发,我就以java为例:

1.校验文本

在 Java 中,正则相关的类在 java.util.regex 中,其中最常用的是 Pattern 和 Matcher,Pattern 是正则表达式对象,Matcher 是匹配到的结果对象,Pattern 和 字符串对象关联,可以得到一个 Matcher。下面是 Java 中匹配的示例:


Java 中目前还没有原生字符串,在之前转义一节讲过,正则需要经过字符串转义和正则转义两个步骤,因此在用到反斜扛的地方,比如表示数字的\d,就得在字符串中表示成\d,转义会让书写正则变得稍微麻烦一些,在使用的时候需要留意一下

2.提取

在 Java 中,可以使用 Matcher 的 find 方法来获取查找到的内容,就像下面这样


3.替换

在 Java 中,一般是使用 replaceAll 方法进行替换,一次性替换所有的匹配到的文本。

4.切割

Java 中切割也是类似的,由于没有原生字符串,转义稍微麻烦点。

5.总结

6.如何理解正则的匹配原理以及优化原则?

用的较少,优化思路参考下图:

7.详解正则常见问题及解决方案

1.问题处理思路

  • 某个位置上可能有多个字符的话,就⽤字符组。
  • 某个位置上有多个字符串的话,就⽤多选结构。
  • 出现的次数不确定的话,就⽤量词。
  • 对出现的位置有要求的话,就⽤锚点锁定位置。
  • 如果是要查找的内容中不能出现某些字符,可以通过使用中括号来排除字符组
  • 如果是内容中不能出现某个子串,比如要求密码是 6 位,且不能有连续两个数字出现。假
    设密码允许的范围是 \w,你应该可以想到使用 \w{6} 来表示 6 位密码
  • 如果里面不能有连续两个数字的话,该如何限制呢?这个可以环视来解决,就是每个字符的后面都不能是两个数字(要注意开头也不能是 \d\d)

2.常见问题及解决方案

1). 匹配数字

  • 数字在正则中可以使用 \d 或 [0-9] 来表示。
  • 如果是连续的多个数字,可以使用 \d+ 或 [0-9]+。
  • 如果 n 位数据,可以使用 \d{n}。
  • 如果是至少 n 位数据,可以使用 \d{n,}。
  • 如果是 m-n 位数字,可以使用 \d{m,n}。

2). 匹配正数、负数和小数

  • 如果希望正则能匹配到比如 3,3.14,-3.3,+2.7 等数字,需要注意的是,开头的正负符号可能有,也可能没有,所以可以使用 [-+]? 来表示
  • 小数点和后面的内容也不一定会有,所以可以使用 (?:.\d+)? 来表示
  • 匹配正数、负数和小数的正则可以写成 [-+]?\d+(?:.\d+)?
  • 非负整数,包含 0 和 正整数,可以表示成[1-9]\d*|0
  • 非正整数,包含 0 和 负整数,可以表示成-[1-9]\d*|0
  • 其中表示正负的符号和小数点可能有,也可能没有,直接用 [-+]?\d+(?:.\d+)? 来表示。

3). 浮点数

  • 负号的时候整数部分不能没有,而正数的时候,整数部分可以没有,所以正则你可以将正负两种情况拆开,使用多选结构写成 -?\d+(?:.\d+)?|+?(?:\d+(?:.\d+)?|.\d+)
  • 负数浮点数表示:-\d+(?:.\d+)?。
  • 正数浮点数表示:+?(?:\d+(?:.\d+)?|.\d+)。
  • 十六进制的数字除了有 0-9 之外,还会有 a-f(或 A-F) 代表 10 到 15 这 6 个数字,所以正则可以写成 [0-9A-Fa-f]+

4). 十六进制数

  • 十六进制的数字除了有 0-9 之外,还会有 a-f(或 A-F) 代表 10 到 15 这 6 个数字,所以
    正则可以写成 [0-9A-Fa-f]+。

5). 手机号码

  • 手机号段比较复杂,如果要兼容所有的号段并不容易。目前来看,前四位是有一些限制,甚至 1740 和 1741 限制了前 5 位号段。我们可以简单地使用字符组和多选分支,来准确地匹配手机号段。如果只限制前 2 位,可以表示成 1[3-9]\d{9},如果想再精确些,限制到前三位,比如使用
    1(?:3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[1389])\d{8}来表示

6). 身份证号码

  • 我国的身份证号码是分两代的,第一代是 15 位,第二代是 18 位。如果是 18 位,最后一位可以是 X(或 x),两代开头都不能是 0,根据规则,你应该能很容易写出相应的正则,第一代可以用 [1-9]\d{14} 来表示,第二代比第一代多 3 位数据,可以使用量词 0 到 1次,
    即写成[1-9]\d{14}(\d\d[0-9Xx])?。

7). 邮政编码

  • 邮编一般为 6 位数字,首位不是 0,比较简单,可以写成 [1-9]\d{5},之前我们也提到过,6 位数字在其它情况下出现可能性也非常大,比如手机号的一部分,身份证号的一部分,所以如果是数据提取,一般需要添加断言,即写成 (?<!\d)[1-9]\d{5}(?!\d)。

8). 腾讯 QQ 号码

  • 目前 QQ 号不能以 0 开头,最长的有 10 位,最短的从 10000(5 位)开始。从规则上我们可以得知,首位是 1-9,后面跟着是 4 到 9 位的数字,即可以使用 [1-9][0-9]{4,9} 来表示。

9). 中文字符

  • 中文属于多字节 Unicode 字符,之前我们讲过比如通过 Unicode 属性,但有一些语言是不支持这种属性的,可以通过另外一个办法,就是码值的范围,中文的范围是 4E00 - 9FFF之间,这样可以覆盖日常使用大多数情况。不同的语言是表示方式有一些差异,比如在 Python,Java,JavaScript 中,Unicode 可以写成 \u码值 来表示,即匹配中文的正则可以写成 [\u4E00-\u9FFF],如果在 PHP 中使用,Unicode 就需要写成 \u{码值} 的样式。

10). IPv4 地址

  • 如果只是验证是不是合法的 IPv4 地址,可以直接使用点号切割,验证一下是不是四个部分,每个部分是不是在 0-255 之间就可以了,比使用正则来校验要简单很多,而且不容易出错。总之正则不是解决问题的唯一方法,我们要在合适的时候使用它,而不是说能用正则的都要用正则来解决。(?:1\d\d|2[0-4]\d|25[0-5]|0?[1-9]\d|0{0,2}\d)(?:.(?:1\d\d|2[0-4]\d|25[0-5]|0?[1-9]\d|0{0,2}\d)){3}

11). 日期和时间

  • 假设日期格式是 yyyy-mm-dd,如果不那么严格,我们可以直接使用 \d{4}-\d{2}-\d{2}。
  • 如果再精确一些,比如月份是 1-12,当为一位的时候,前面可能不带 0,可以写成 01 或1,月份使用正则,可以表示成 1[0-2]|0?[1-9],日可能是 1-31,可以表示成[12]\d|3[01]|0?[1-9],这里需要注意的是 0?[1-9] 应该放在多选分支的最后面,因为放最前面,匹配上一位数字的时候就停止了(示例),正确的正则(示例)应该是
    \d{4}-(?:1[0-2]|0?[1-9])-(?:[12]\d|3[01]|0?[1-9])。
  • 时间格式比如是 23:34,如果是 24 小时制,小时是 0-23,分钟是 0-59,所以可以写成(?:2[0-3]|1\d|0?\d)😦?:[1-5]\d|0?\d)。
  • 日期中月份还有大小月的问题,比如 2 月闰年可以是 29 日,使用正则没法验证日期是不是正确的。我们也不应该使用正则来完成所有事情,而是只使用正则来限制具体的格式,比如四位数字,两位数字之类的,提取到之后,使用日期时间相关的函数进行转换,如果失败就证明不是合法的日期时间。

12). 邮箱

  • 格式是 用户名 @主机名,用户名部分通常可以有英文字母,数字,下划线,点等组成,但其中点不能在开头,也不能重复出现,比如:[a-zA-Z0-9_.±]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+。

13). 网页标签

  • 配对出现的标签,比如 title,一般网页标签不区分大小写,我们可以使用 (?i)来进行匹配。在提取引号里面的内容时,可以使用 [^"]+,方括号里面的内容时,可以使用 [^>]+ 等方式。我们通过一些常见的问题,逐步进行分析,讲解了正则表达式书写时的思路,和一些常见的错误。这些正则如果用于校验,还需要添加断言,比如 \A 和 \z(或\Z),或 ^ 和 $。如果用于数据提取,还应当在首尾添加相应的断言。

总结

结束语:

咱们学习任何内容,在一开始时,都不要过分去注重细节,重要的是掌握正确的方法,先从整体上入手,掌握核心的概念。比如当你学习了字符组、多选结构、量词、锚点、贪婪 & 非贪婪、流派、匹配原理这些核心知识之后,你要在后续遇到问题时,查阅一下相关文档,很快就可以解决掉了。

1.如何检验自己的掌握程度

当你觉得你掌握了正则之后,你可以尝试把它教给别人,或者你可以想一下,如果让你来讲正则,你会怎么讲?这样能够让你有更深刻的理解

2.熟练运用,而不滥用

有时候在学习正则之后,遇到问题总是想“展示一下身手”,这种心理无可厚非,但一定要记住在使用正则的过程中,一定要克制

3.如何进一步成长?

在这个技术太多,变化太快的时代,我们需要不断地学习。越是基础的内容越重要,一次性多投入些时间,弄清楚,搞明白。多动手练习,实践出真知

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
ASP.NET 中的正则表达式
ASP
快速回忆正则表达式
python中级----正则表达式进阶
正则表达式30分钟入门教程
JS正则表达式一条龙讲解,从原理和语法到JS正则、ES6正则扩展,最后再到正则实践思路
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服