正则表达式
正则
入门
[/code/g]匹配 2020 的数据
正则表达式可以匹配某些特定的数据,如果你想要从庞大的文字信息中提取出一小段你需要的数据,那么正则表达式或许能帮到你。
例如:输入 code就可以匹配所有包含code的数据(图片中code左边的/和右边的的/g暂时可以忽略)

[] 字符组
如果只是使用正则表达式来匹配文本,没有什么意义,毕竟检测一个文本中是否有另一个字符串本来就非常简单。
正则表达式强大的地方在于它可以迅速地用极简单的方式达到字符串的复杂控制。
字符组([])允许匹配一组可能出现的字符。

可以发现[Pp]既可以匹配大写的P也可以匹配小写的p
练习:使用字符组匹配Ruby、Rube、ruby、rube。
[Rr]ub[ye]

- 区间
有一些常见的字符组非常大,比如,我们要匹配任意的数字,如果依照上述代码,每次我们都需要使用[0123456789]。
但是这样好吗?
如果要匹配从a-z的字母呢?我想你肯定不愿意从a写到z了!
为了适应这一点,正则表达式引擎在字符组中使用连字符(-)代表区间,依照这个规则,我们可以总结出三点:
- 要匹配任意数字可以使用
[0-9]; - 如果想要匹配所有小写字母,可以写成
[a-z]; - 想要匹配所有大写字母可以写成
[A-Z]。
例如:
练习:匹配数据所有的数字、小写字母和大写字母。
[a-zA-Z0-9]

** \ 匹配特殊字符**
正则表达使用了 - 号代表了区间,但是我们有时候需要匹配的符号就是 -号,该怎么办呢?
这个时候我们需要对-号进行转义操作,即 \-。
在正则中使用 \ 就可以进行对特殊符号进行转义,对 - 进行转义就可以表示为 \-,即 \- 就代表了 - 号本身。
偷偷告诉你,转义符
\也适用于其他的符号,例如匹配圆括号可以使用\(
例如:

练习:编写正则表达式匹配下列符号。
[[\[\]\-\(]]

匹配字母
[]
字符组中可以放多个条件例如,想要匹配数字的小写字母可以这样写:[0-9a-z]
练习:
使用正则表达式匹配字母,规则如下:
- 匹配
a-z的小写字母; - 匹配
A-F的大写字母;
[a-zA-F]

匹配目标数据
找出下列数据的规律,然后进行匹配。
[a-f0-3]

** ^ 取反**
到目前为止,我们定义的字符组都是由可能出现的字符定义,不过有时候我们可能希望根据不会出现的字符定义字符组。
例如:匹配不包含数字的字符组

可以通过在字符数组开头使用 ^ 字符实现取反操作,从而可以反转一个字符组(意味着会匹配任何指定字符之外的所有字符)。
再看一个例子:

这里的 n[^e] 的意思就是n后面的字母不能为 e。
不含小写字母的数据
编写正则表达式,匹配不包含小写字母的数据。
[^a-z]

快捷方式
\d \w 快捷匹配数字和字母
以目前学到的内容,如果想要匹配所有的字母,会使用[A-Za-z],要匹配数字会使用[0-9]
还有没有更简洁的方式呢?
正则表达式引擎提供了一些快捷方式如:\w 可以与任意单词字符匹配。
当我们想要匹配任意数字的时候也可以使用快捷方式\d,d即digit数字的意思,等价于[0-9]。
| 快捷方式 | 描述 |
|---|---|
| \w | 与任意单词字符匹配,任意单词字符表示 [A-Z]、 [a-z]、[0-9]、_ |
| \d | 与任意数字匹配 |
\s 匹配空白
\s快捷方式可以匹配空白字符,比如空格,tab、换行等。

练习:匹配空白分隔的单词
[\s]

\b 单词边界
\b 匹配的是单词的边界,例如,

\bmaster\b 就仅匹配 有边界的master单词,没边界的不匹配。
匹配数字和小写字母
[\da-z]
uploading-image-702604.png
[\W] 快捷方式取反
快捷方式也可以取反,例如对于\w的取反为\W,将小写改写成大写即可,其他快捷方式也遵循这个规则。
练习:匹配下列开头不以字母开头的单词。
[\W]

^ 开始和结束 $
正则表达式中
^ 指定的是一个字符串的开始,

$ 指定的是一个字符串的结束。

练习:匹配以OS结尾的字符串。
OS$

. 任意字符
.字符代表匹配任何单个字符,它只能出现在方括号以外。
值得注意的是: .字符只有一个不能匹配的字符,也就是换行符(\n),不过要让.字符与换行符匹配也是可以的,以后会讨论。
示例:

练习:
匹配任意字母之后是ar的字符串。
.ar

? 可选字符
有时,我们可能想要匹配一个单词的不同写法,比如color和colour,或者honor与honour。
这个时候我们可以使用 ? 符号指定一个字符、字符组或其他基本单元可选,这意味着正则表达式引擎将会期望该字符出现零次或一次。
?的作用就是匹配它之前的字符0次或1次。
例如:

在这里 u? 表示u是可选的,即可以出现也可以不出现,可以匹配的是 honor 和 honour 。
匹配多个数据
{N} 重复
到目前为止,我们只是学习了关于仅出现一次的字符串匹配,在实际开发中,肯定不能满足需求,比如要匹配电话号码、身份证的时候就无法满足需求了。
如果遇到这样的情况,我们可能期望一个字符组连续匹配好几次。
在一个字符组后加上{N} 就可以表示在它之前的字符组出现N次。
例如:

练习:匹配电话号码,匹配所有的电话号码。
\d{3}-\d{5}

{M,N} 重复区间
可能有时候,我们不知道具体要匹配字符组要重复的次数,比如身份证有15位也有18位的。
这里重复区间就可以出场了,语法:{M,N},M是下界而N是上界。
举个例子:

\d{3,4} 既可以匹配3个数字也可以匹配4个数字,不过当有4个数字的时候,优先匹配的是4个数字,这是因为正则表达式默认是贪婪模式,即尽可能的匹配更多字符,而要使用非贪婪模式,我们要在表达式后面加上 ?号。

练习:匹配电话号码
使用正则表达式提取电话号码,假设电话号码有两种规则:
- 以
3个数字开头,后面7个数字,例如:020-7281333 - 以
4个数字开头,后面7个数字,例如:0731-8283431
现在请你使用一个正则表达式匹配所有符合这两种规则的电话号码。
\d{3,4}-\d{7}

+ * 开闭区间
有时候我们可能遇到字符组的重复次数没有边界,例如:

闭区间不写即可表示匹配一个或无数个。
速写
还可以使用两个速写字符指定常见的重复情况,可以使用 + 匹配1个到无数个,使用 *代表0个到无数个。
即:+等价于{1,},*等价于{0,}。
+号示例:
*号示例:
匹配所有手机号码
使用正则表达式匹配手机号码,假设手机号码规则如下:
- 必须是
11位的数字; - 第一位数字必须以
1开头,第二位数字可以是[3,4,5,7,8]中的任意一个,后面9个数是[0-9]中的任意一个数字。
1[3,4,5,7,8][0-9]{9}

匹配网站地址
匹配以 http开头,以/结尾的所有数据。
^http+.*/$

修饰符
g 修饰符
g 修饰符可以查找字符串中所有的匹配项:
i 修饰符
i 修饰符为不区分大小写匹配,实例如下:

m 修饰符
m 修饰符可以使 ^ 和 $ 匹配一段文本中每行的开始和结束位置。
g 只匹配第一行,添加 m 之后实现多行。

s 修饰符
默认情况下的圆点 . 是 匹配除换行符 \n 之外的任何字符,加上 s 之后, . 中包含换行符 \n。

实践
1 匹配电话号码
匹配电话号码,假设电话号码可以有下列两种方式:
- 0XX-XXXXXXX,例如
020-8810456; - 0XXXXXXXXX,例如
0208810456。
020 代表区号,8810456是电话号码,区号第一个数字必须是0,电话号码的第一个数字必须大于等于1。
^0\d{2}-?[1-9]\d{6}

2 匹配所有王姓同学的信息
^王.+?\d{4}

总结
多种匹配模式
| 实例 | 描述 |
|---|---|
[Pp]ython |
匹配 “Python” 或 “python”。 |
rub[ye] |
匹配 “ruby” 或 “rube”。 |
[abcdef] |
匹配中括号内的任意一个字母。 |
[0-9] |
匹配任何数字。类似于 [0123456789]。 |
[a-z] |
匹配任何小写字母。 |
[A-Z] |
匹配任何大写字母。 |
[a-zA-Z0-9] |
匹配任何字母及数字。 |
[^au] |
除了au字母以外的所有字符。 |
[^0-9] |
匹配除了数字外的字符。 |
| 实例 | 描述 |
|---|---|
. |
匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。 |
? |
匹配一个字符零次或一次,另一个作用是非贪婪模式 |
+ |
匹配1次或多次 |
* |
匹配0次或多次 |
\b |
匹配一个长度为0的子串 |
\d |
匹配一个数字字符。等价于 [0-9]。 |
\D |
匹配一个非数字字符。等价于 [^0-9]。 |
\s |
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。 |
\S |
匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 |
\w |
匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。 |
\W |
匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]‘。 |
分组
在正则表达式中还提供了一种将表达式分组的机制,当使用分组时,除了获得整个匹配。还能够在匹配中选择每一个分组。
要实现分组很简单,使用()即可。
例如:

这段正则表达式将文本分成了两组,第一组为:0731,第二组为8825951。
分组有一个非常重要的功能——捕获数据。所以()被称为捕获分组,用来捕获数据,当我们想要从匹配好的数据中提取关键数据的时候可以使用分组。
(\d{4}) 和 (\d{7})就分别捕获了两段数据:
07318825951
或者条件
使用分组的同时还可以使用 或者(or)条件。
例如要提取所有图片文件的后缀名,可以在各个后缀名之间加上一个 |符号:

非捕获分组
有时候,我们并不需要捕获某个分组的内容,但是又想使用分组的特性。
这个时候就可以使用非捕获组(?:表达式),从而不捕获数据,还能使用分组的功能。
例如想要匹配两个字母组成的单词或者四个字母组成的单词就可以使用非捕获分组:

使用:
使用正则表达式将其中的年月日全都提取出来。

断言
正向先行断言
很多人也称先行断言和后行断言为环视,也有人叫预搜索,其实叫什么无所谓,重要的是知道如何使用它们!
先行断言和后行断言总共有四种:
- 正向先行断言
- 反向先行断言
- 正向后行断言
- 反向后行断言
正向先行断言:(?=表达式),指在某个位置向右看,表示所在位置右侧必须能匹配表达式
例如:
我喜欢你 我喜欢 我喜欢我 喜欢 喜欢你
如果要取出喜欢两个字,要求这个喜欢后面有你,这个时候就要这么写:喜欢(?=你),这就是正向先行断言。

提取包含大小写字母的字符串

密码强度验证
编写正则表达式进行密码强度的验证,规则如下:
- 至少一个大写字母
- 至少一个小写字母
- 至少一个数字
- 至少
8个字符
左边为需要你的正则需要匹配的,右边的字符串是你的正则不需要匹配的。
(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(.{8})
反向先行断言
反向先行断言(?!表达式)的作用是保证右边不能出现某字符。
例如: 我喜欢你 我喜欢 我喜欢我 喜欢 喜欢你
如果要取出喜欢两个字,要求这个喜欢后面没有你,这个时候就要这么写:喜欢(?!你),这就是反向先行断言。
排除邮箱
编写正则表达式匹配不是qq邮箱的数据。
.+@(?!qq).+.com
正向后行断言
本小节只需要你记住一句话:先行断言和后行断言只有一个区别,即先行断言从左往右看,后行断言从右往左看。
正向后行断言:(?<=表达式),指在某个位置向左看,表示所在位置左侧必须能匹配表达式
例如:如果要取出喜欢两个字,要求喜欢的前面有我,后面有你,这个时候就要这么写:(?<=我)喜欢(?=你)。
匹配王姓同学的名字
(?<=王). 姓名前面必须有王,这意思
反向后行断言
反向后行断言:(?<!表达式),指在某个位置向左看,表示所在位置左侧不能匹配表达式
例如:如果要取出喜欢两个字,要求喜欢的前面没有我,后面没有你,这个时候就要这么写:(?<!我)喜欢(?!你)。

总结起来就一句话,正向,可以匹配,反向不可以匹配
先行,某个位置向右看必须匹配,后行,某个位置向左看不可以匹配。
正向先行 <?= 正向后行 <?<=
反向先行 <?
本文来自博客园,作者:走马!,转载请注明原文链接:https://www.cnblogs.com/zou-ma/p/15923625.html

浙公网安备 33010602011771号