正则表达式

1.什么是正则表达式

正则表达式(Regular Expression)

正则表达式是一种字符串匹配规则,用于匹配或替换字符串。

2.单字符

a-z

A-Z

0-9

\d 匹配0-9任意一个数字

\D 匹配除0-9以外的任意一个字符

\w 匹配数字、字母、下划线

\W 匹配非数字、字母、下划线

\s 匹配空白字符

\S 匹配非空白字符

. 除了\n以外的任意一个字符

[] 匹配中括号中任意一个字符

[^] 匹配除中括号中以外任意一个字符

3.量词

* 任意次, 可以是0次

+ 1次 或 多次

? 0次 或 1次

{m} 匹配前一个字符的重复次数为m次

4.其他

$ 结尾处 边界处理

^ 起始处 边界处理

\b 单词边界

\B 非单词边界

| 或者

()

上面这种分类是小编觉得比较容易理解的一种分类,在看其他文档或资料的时候,并不一定是这样划分的。

5.实战演练

这里以python语言为例,详解正则表达式的使用。

python语言中,我们需要导入一个re模块才能使用正则表达式

导入re模块

1
import re

python语言中使用正则表达式非常简单,语法也非常简洁。

主要有以下几个方法

re.match() 字符串起始位置从左往右检索,如果匹配不到则停止检索

re.search()字符串任意位置从左往右检索,匹配到则停止

re.findall() 字符串起始位置从左往右检索,找到所有符合的字符串,返回一个列表

re.split() 字符串分割

re.sub() 正则替换

re.compile() 编译

接下来,我们来看几个案例

电话号码匹配

电话号码都是数字,且长度为11位

1
2
3
4
5
str_ = "我的电话号码是18888888888, 有事情随时打给我"

res = re.match("\d{11}", str_) # 匹配11个数字

print(res) # None

上面的正则表达式是正确的,\d代表0-9任意一位数字,但是为什么匹配不到呢?原因就是match方法是从字符串的起始位置开始匹配的,str_字符串的起始位置是”我的电话…”,所以就匹配不到了。如果我们想要从字符串的任意位置开始匹配,这个时候就需要使用search方法了。

示例代码如下:

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是16888888888, 有事情随时打给我"

res = re.search("\d{11}", str_) # 匹配11个数字

print(res) # <re.Match object; span=(7, 18), match='16888888888'>

可以看到,当我们换成search方法后,可以匹配到结果,但是打印输出并不是16888888888。如果我们想要拿到匹配的字符串需要使用res.group()获取

示例代码如下:

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是16888888888, 有事情随时打给我"

res = re.search("\d{11}", str_) # 匹配11个数字

print(res.group()) # 16888888888

现在我们已经可以拿到匹配的字符串了,但是我们思考一个问题,16888888888这个号码存在?显然是不存在的,所以我们需要对手机号码格式做一定的限制。

手机号码格式要求如下:

第一位必定为1

第二位必定为3或4或5或7或8

其他位置的可以为0-9

那这个正则表达式如何书写呢?请看以下示例

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是16888888888, 有事情随时打给我"

res = re.search("1[34578]\d{9}", str_) # 电话号码匹配

print(res) # None

[]匹配中括号中任意一个字符,我们对号码做了一定的限制,第1位必须是数字1,第2位必须是3 | 4 | 5 | 7 | 8, 第3位数字没有格式要求。

可以看到,我们打印的结果是None,因为16888888888号码中的第二位并不符合我们的要求。

现在好像很完美了,但是还是存在一些小问题。请看以下示例代码

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是18888888888999, 有事情随时打给我"

res = re.search("1[34578]\d{9}", str_) # 匹配11个数字

print(res.group()) # 18888888888

上面还是可以匹配到,但显然18888888888999并不是一个号码,因此我们还需要做一层限制。示例代码如下

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是18888888888999, 有事情随时打给我"

res = re.search("1[34578]\d{9}[^\d]", str_) # 匹配11个数字

print(res) # None

我们限制一下匹配到11位后面不能再是数字,如果是数字就匹配不到。

那么这样就完美了?请看以下代码示例j

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是18888888888, 有事情随时打给我"

res = re.search("1[34578]\d{9}[^\d]", str_) # 匹配11个数字

print(res.group()) # 18888888888,

无缘无故多匹配了一个, 这种结果并不是我们想要的,如何处理呢?请看示例

1
2
3
4
5
6
7
8
import re

str_ = "我的电话号码是18888888888, 有事情随时打给我"

res = re.search("(1[34578]\d{9})[^\d]", str_) # 匹配11个数字

print(res.group()) # 18888888888,
print(res.group(1)) # 18888888888

我们只需要将我们想要匹配的部分用()括起来。想要获取结果的时候,需要这样取,res.group(1) res.group()默认还是取匹配到的结果,()就是第1个分组。

那么这样就完美了?或许你也已经想到了,如果电话号码第一位前面也是数字呢? 请看代码示例

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是22222218888888888, 有事情随时打给我"

res = re.search("(1[34578]\d{9})[^\d]", str_) # 匹配11个数字

print(res.group(1)) # 18888888888

你应该想到如何解决了吧,示例代码如下

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是22222218888888888, 有事情随时打给我"

res = re.search("[^\d](1[34578]\d{9})[^\d]", str_) # 匹配11个数字

print(res) # None

这样,我们就保证了手机号格式的正确性。

或许你看到过网上的文章是这样使用的,示例代码如下

1
2
3
4
5
6
7
import re

str_ = "我的电话号码是22222218888888888, 有事情随时打给我"

res = re.search("^1[34578]\d{9}$", str_) # 匹配11个数字

print(res) # None

正则表达式是这样写得^1[34578]\d{9}$,那么为什么这里匹配不到呢?

前面已经说过^代表字符串的起始位置,$代表字符串的结束位置。那我问你,str_字符串的起始位置是1? 结束位置是数字0-9任意一个?显然不是啊。如果修改一下,就可以正常匹配

示例代码如下

1
2
3
4
5
6
7
import re

str_ = "18888888888"

res = re.search("^1[34578]\d{9}$", str_) # 匹配11个数字

print(res)

这样就可以正常匹配呢。

使用这个^1[34578]\d{9}$正则表达式是一般用于手机号码的表单验证。防止用户乱输手机号(这种情况是存在的)限制你必须输入11位手机号,而且格式也必须符合要求。

以上就是本篇文章的全部内容

6.总结

本篇文章详细介绍了什么是正则表达式,正则表达式在python中的使用等内容。并且通过一个实战案例将大部分知识点穿插应用。

附:

各大运营商手机格式

  • 移动:134、135、136、137、138、139、147(无线上网卡)、150、151、152、157、158、159、182、183、187、188、178
  • 联通:130、131、132、145(无线上网卡)、155、156、185(iPhone5上市后开放)、186、176(4G号段)175(2015年9月10日正式启用,暂只对北京、上海和广东投放办理)
  • 电信:133、153、180、181、189、177、173、149

正则表达式在线测试网址:

https://rubular.com/

https://www.regexpal.com/


正则表达式
http://cxycsx.vip/2023/08/31/其他/正则表达式/
作者
程序员陈师兄
发布于
2023年8月31日
许可协议