Python -- 正则表达式
创始人
2024-04-27 00:59:56
0

目录

1.介绍

1.1 特点:

1.2 Python中的正则表达式

2.正则查找

2.1 查找方法的使用

2.2 match方法的使用

2.3 search方法的使用

2.4 re.match与re.search的区别

2.5 findall方法的使用

2.6 finditer方法的使用

3.re.Match类

4.re.complie的使用

5.正则修饰符

6.正则模式

6.1 非打印字符

6.2 特殊字符

6.3 定位符

6.4 限定符

7.正则替换

8.贪婪模式和非贪婪模式


1.介绍

正则表达式是一个特殊的字符序列,计算机科学的一个概念。通常被用来检索、替换那些符合某个模式(规则)的文本。

许多程序设计语言都支持利用正则表达式进行字符串操作。在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用re模块。re 模块使 Python 语言拥有全部的正则表达式功能。

1.1 特点:

  1. 灵活性、逻辑性和功能性非常强;

  2. 可以迅速地用极简单的方式达到字符串的复杂控制。

  3. 对于刚接触的人来说,比较晦涩难懂。

1.2 Python中的正则表达式

与大多数编程语言相同,正则表达式里也使用\作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符\,那么使用编程语言表示的正则表达式里将需要4个反斜杠\:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。

 print(re.match('\\\\', '\hello'))  # 需要使用四个反斜杠来匹配一个 \

Python里的原生字符串很好地解决了这个问题,有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。在Python 字符串前面添加r即可将字符串转换成为原生字符串。

print(re.match(r'\\', '\hello')) # 使用两个反斜杠即可匹配一个 \

2.正则查找

2.1 查找方法的使用

在Python中的查找匹配方法,常见的有下面四种,他们的用法大致相同,但是匹配出的结果却不同。

  • match方法(只匹配字符串开头)

  • search方法(扫描整个字符串,找到第一个匹配)

  • findall方法(扫描整个字符串,找到所有的匹配)

  • finditer方法(扫描整个字符串,找到所有的匹配,并返回一个可迭代对象)

2.2 match方法的使用

re.match尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

函数语法:

re.match(pattern,string,flags=0)
参数描述
pattern匹配的正则表达式
string要匹配的字符串。
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

我们可以使用group(num)函数来获取匹配表达式。

import reresult1 = re.match(r'H','Hello')result2 = re.match(r'e','Hello')print(result1.group(0)) # 'H' 匹配到的元素print(result1.span()) # (0,1) 匹配到的元素所在位置print(result2)  # None

2.3 search方法的使用

re.search 扫描整个字符串并返回第一个成功的匹配。

函数语法:

re.search(pattern, string, flags=0)

示例:

 import reresult1 = re.search(r'He','Hello')result2 = re.search(r'lo','Hello')print(result1.group(0))  # Heprint(result1.span()) # (0,2)print(result2.group(0)) # loprint(result2.span()) # (3,5)

2.4 re.match与re.search的区别

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

示例:

 result1 = re.search(r'天气','今天天气不错哟')result2 = re.match(r'天气','今天天气不错哟')print(result1)  # print(result2) # None

2.5 findall方法的使用

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

注意: match 和 search 是匹配一次 findall 匹配所有。

语法格式:

re.findall(pattern,string,flags=0)

示例代码:

ret = re.findall(r'\d+','he23ll34')
print(ret)  # ['23', '34']
ret = re.match(r'\d+','he23ll34') 
print(ret) # None match只匹配开头,所以匹配到
ret = re.search(r'\d+','he23ll34')
print(ret) #  search 只能匹配到一个数字
  • 注意事项:

findall方法匹配时,如果匹配规则里有分组,则只匹配分组数据。

ret = re.findall(r'\w+@(qq|126|163)\.com','123@qq.com;aa@163.com;bb@126.com')
print(ret)  # ['qq', '163', '126']  只匹配到了分组里的内容

        如果正则表达式里存在多个分组,则会把多个分组匹配成元组。

ret = re.findall(r'\w+@(qq|126|163)(\.com)','123@qq.com;aa@163.com;bb@126.com')
print(ret) #[('qq', '.com'), ('163', '.com'), ('126', '.com')]

        如果想要让findall匹配所有的内容,而不仅仅只是匹配正则表达式里的分组,可以使用 ?:来将分组标记为非捕获分组。

ret = re.findall(r'\w+@(?:qq|126|163)\.com','123@qq.com;aa@163.com;bb@126.com')
print(ret) # ['123@qq.com', 'aa@163.com', 'bb@126.com']

2.6 finditer方法的使用

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

ret = re.finditer(r'\d+','he23ll34')  # 得到的结果是一个可迭代对象
for x in ret: # 遍历 ret 取出里面的每一项匹配print(x.group(), x.span()) # 匹配对象里的group保存了匹配的结果

3.re.Match类

当我们调用re.match方法、re.search方法,或者对re.finditer方法的结果进行迭代时,拿到的数据类型都是re.Match对象。

x = re.match(r'h','hello')
y = re.search(r'e','hello')
z = re.finditer(r'l','hello')
print(type(x))  # 
print(type(y)) # 
for a in z:print(type(a)) # 

这个类里定义了相关的属性,可以直接让我们来使用。

属性和方法说 明
pos搜索的开始位置
endpos搜索的结束位置
string搜索的字符串
re当前使用的正则表达式的对象
lastindex最后匹配的组索引
lastgroup最后匹配的组名
group(index=0)某个分组的匹配结果。如果index等于0,便是匹配整个正则表达式
groups()所有分组的匹配结果,每个分组的结果组成一个列表返回
groupdict()返回组名作为key,每个分组的匹配结果座位value的字典
start([group])获取组的开始位置
end([group])获取组的结束位置
span([group])获取组的开始和结束位置
expand(template)使用组的匹配结果来替换模板template中的内容,并把替换后的字符串返回
ret = re.search(r'(abc)+', 'xxxabcabcabcdef')
print(ret.pos)  # 搜索开始的位置,默认是0
print(ret.endpos)  # 搜索结束的位置,默认是字符串的长度
print(ret.group(0)) # abcabcabc 匹配整个表达式
print(ret.group(1))  # abc 第一次匹配到的结果
print(ret.span()) # (3, 12) 开始和结束位置
print(ret.groups())  # 表示当正则表达式里有多个分组时,多个分组的匹配结果

4.re.complie的使用

我们在使用正则表达式时,可以直接调用re 模块的 match,search,findall等方法,传入指定的正则表达式。同时,也可以调用re.compile方法,生成一个正则表达式对象,再调用这个正则表达式对象的相关方法实现匹配。

示例:

re.match(r'h','hello')  # 可以使用re.match方法直接匹配
# 也可以调用re模块的compile方法,生成一个 Pattern 对象,再调用 Pattern 对象的 match方法
regex = re.compile(r'h')
regex.match('hello')re.search(r'l','hello')
regex = re.compile(r'l')
regex.match('hello')regex = re.compile(r'l')
regex.findall('hello')regex = re.complie(r'l')
regex.finditer('hello')

5.正则修饰符

修饰符描述
re.I使匹配对大小写不敏感
re.M多行匹配,影响 ^ 和 $
re.S使 . 匹配包括换行在内的所有字符

示例:

print(re.search(r'L','hello'))  # None
print(re.search(r'L', 'hello', re.I))  # 不区分大小写# \w+$ 表示匹配以一个或者多个字母结尾
# re.M 可以进行多行匹配,每个换行都认为是一个结尾
print(re.findall(r'\w+$','i am boy\n you are girl\n he is man',re.M)) # ['boy', 'girl', 'man']
# 不实用re.M修饰符,只会匹配到最后的 man
print(re.findall(r'\w+$','i am boy\n you are girl\n he is man')) # ['man']print(re.search(r'.','\n')) # None . 匹配除了 \n 以外的所有字符
print(re.search(r'.','\n',re.S)) # '\n'  匹配到了 \n

6.正则模式

模式字符串使用特殊的语法来表示一个正则表达式:

  1. 字母和数字表示他们自身,一个正则表达式模式中的字母和数字匹配同样的字符串。

    re.search(r'H','Hello')  # 这里的 H 表示的就是字母 H 自身,代表有特殊含义
  2. 多数字母和数字前加一个反斜杠时会拥有不同的含义。

    ret = re.search(r'\d','he12ms90') # 这里的 \d 表示的是匹配数字
  3. 标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。

    ret = re.search(r'.','hello') # 这里的 . 表示的是匹配任意字符
    ret = re.search(r'\.','he.llo')  # 这里的 \. 进行了转义,才表示标点符号自身。
  4. 反斜杠本身需要使用反斜杠转义。由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'\t',等价于\\t )匹配相应的特殊字符。

下表列出了正则表达式模式语法中的特殊元素,如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。

6.1 非打印字符

非打印字符也可以是正则表达式的组成部分。下表列出了表示非打印字符的转义序列:

字符描述
\cx匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
\f匹配一个换页符。等价于 \x0c 和 \cL。
\n匹配一个换行符。等价于 \x0a 和 \cJ。
\r匹配一个回车符。等价于 \x0d 和 \cM。
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。注意 Unicode 正则表达式会匹配全角空格符。
\S匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
\t匹配一个制表符。等价于 \x09 和 \cI。
\v匹配一个垂直制表符。等价于 \x0b 和 \cK。

6.2 特殊字符

所谓特殊字符,就是一些有特殊含义的字符。若要匹配这些特殊字符,必须首先使字符"转义",即,将反斜杠字符\ 放在它们前面。下表列出了正则表达式中的特殊字符:

特殊字符描述
( )标记一个子表达式的开始和结束位置。子表达式可以获取供以后使用。要匹配这些字符,请使用 \( 和 \)。
.匹配除换行符 \n 之外的任何单字符。要匹配 . ,请使用 \. 。
[标记一个中括号表达式的开始。要匹配 [,请使用 \[。
\将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如, 'n' 匹配字符 'n'。'\n' 匹配换行符, \\ 匹配 \,而 \( 则匹配 ( 。
{标记限定符表达式的开始。要匹配 {,请使用 \{
|指明两项之间的一个选择。要匹配 |,请使用 |。
\d匹配一个数字字符。等价于 [0-9]。
[0-9]匹配任何数字。等价于 \d
\D匹配一个非数字字符。等价于 [^0-9]
[a-z]匹配任何小写字母
[A-Z]匹配任何大写字母
[a-zA-Z0-9]匹配任何字母及数字。等价于\w
\w匹配包括下划线的任何单词字符。等价于[A-Za-z0-9_]
\W匹配任何非单词字符。等价于 [^A-Za-z0-9_]
[\u4e00-\u9fa5]匹配纯中文

6.3 定位符

定位符使您能够将正则表达式固定到行首或行尾。它们还使您能够创建这样的正则表达式,这些正则表达式出现在一个单词内、在一个单词的开头或者一个单词的结尾。

定位符用来描述字符串或单词的边界,^$ 分别指字符串的开始与结束,\b 描述单词的前或后边界,\B 表示非单词边界。

正则表达式的定位符有:

特殊字符描述
^匹配输入字符串的开始位置,例如:^h匹配以h开头;在方括号表达式中时,它表示不接受该字符集合,例如[^0-9]匹配除了数字以外的数据。要匹配 ^ 字符本身,请使用 \^。
$匹配输入字符串的结尾位置。要匹配 $ 字符本身,请使用 \$
\b匹配一个单词边界,即字与空格间的位置。
\B非单词边界匹配。

6.4 限定符

限定符用来指定正则表达式的一个给定组件必须要出现多少次才能满足匹配。有 *+?{n}{n,}{n,m} 共6种。

正则表达式的限定符有:

字符描述
*匹配前面的子表达式零次或多次。例如,zo 能匹配 "z" 以及 "zoo"。 等价于{0,}。
+匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
?匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 、 "does" 中的 "does" 、 "doxy" 中的 "do" 。? 等价于 {0,1}。
{n}n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,}n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。

示例:

re.search(r'\s','大家好 我是 代码')  # 匹配所有的空字符
re.search(r'\S','大家') # 匹配所有的非空字符
re.search(r'\n','大家好\n我是代码') # 匹配换行
re.search(r'n$','hello python') # 匹配以 n 结尾
re.search(r'^h.+n$','hello python') # 匹配以 h 开头,中间出现一次或多次任意字符,并且以n结尾
re.search(r'^ha*','h')  # 匹配以 h 开头,a出现0次或者一次

练习:

  1. 用户名匹配:由数字、大小写字母、下划线_和中横线-组成,长度为4到14位,并且不能以数字开头。

    r'^\D[a-z0-9A-Z_\-]{3,13}', 'sH_8'
  2. 匹配邮箱

    r'^([A-Za-z0-9_\-\.])+@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$
  3. 匹配手机号

    r'^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$'
  4. 匹配身份证号

    r'^[1-9]\d{5}(18|19|20|)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$'
  5. 匹配URL地址

    r'((ht|f)tps?):\/\/([\w\-]+(\.[\w\-]+)*\/)*[\w\-]+(\.[\w\-]+)*\/?(\?([\w\-\.,@?^=%&:\/~\+#]*)+)?'
  6. 匹配QQ号

    r'^[1-9][0-9]{4,10}$'
  7. 匹配微信号

    r'^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$'
  8. 匹配车牌号

    r'^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳

7.正则替换

Python中的re模块提供了re.sub用户替换字符串中的匹配项。

语法:

re.sub(pattern,repl,string,count=0)

参数:

  • pattern : 正则中的模式字符串。

  • repl : 替换的字符串,也可为一个函数。

  • string : 要被查找替换的原始字符串。

  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。

phone = "2004-959-559 # 这是一个电话号码"# 删除注释
num = re.sub(r'#.*$', "", phone)
print ("电话号码 : ", num)# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print ("电话号码 : ", num)

repl可以使用一个字符串用来表示替换后的结果以外,还可以传入一个函数。

def double(matched):test = int(matched.group('test'))return str(test * 2)print(re.sub(r'(?P\d+)', double, 'hello23hi34'))  # hello46hi68

8.贪婪模式和非贪婪模式

Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;

非贪婪则相反,总是尝试匹配尽可能少的字符。

*,?,+,{m,n}后面加上 ?使贪婪变成非贪婪。

 >>> s="This is a number 234-235-22-423">>> r=re.match(".+(\d+-\d+-\d+-\d+)",s)>>> r.group(1)'4-235-22-423'>>> r=re.match(".+?(\d+-\d+-\d+-\d+)",s)>>> r.group(1)'234-235-22-423'>>>

正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“.+”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“\d+”只需一位字符就可以匹配,所以它匹配了数字“4”,而“.+”则匹配了从字符串起始到这个第一位数字4之前的所有字符。

 >>> re.match(r"aa(\d+)","aa2343ddd").group(1)'2343'>>> re.match(r"aa(\d+?)","aa2343ddd").group(1)'2'>>> re.match(r"aa(\d+)ddd","aa2343ddd").group(1)'2343'>>> re.match(r"aa(\d+?)ddd","aa2343ddd").group(1)'2343'>>>

相关内容

热门资讯

los系统和安卓系统的区别,两... 你有没有想过,为什么你的手机有时候运行得那么顺畅,有时候又卡得像蜗牛呢?这背后其实隐藏着两个大玩家—...
安卓系统可以安装cad软件,安... 你有没有想过,在安卓手机上也能轻松安装CAD软件呢?没错,就是那个专业的设计软件,以前只能在电脑上操...
车载ce系统与安卓系统的区别,... 你有没有想过,为什么你的车载系统有时候那么不智能,而安卓手机却总能给你带来惊喜?今天,就让我带你深入...
苹果6s系统换安卓系统,体验安... 你有没有想过,把你的苹果6s换成安卓系统呢?想象那流畅的触控体验,加上安卓那丰富的应用和可定制的界面...
安卓转移ios健康系统,探索健... 你有没有想过,从安卓手机转到iOS设备后,那些积累的健康数据怎么办呢?别急,今天就来给你详细解析如何...
安卓系统如何换微信号,教你如何... 你是不是也和我一样,对安卓系统换微信号这个话题感兴趣呢?毕竟,谁不想偶尔换个心情,换个昵称呢?好啦,...
安卓机清理系统内存,提升手机运... 手机用久了是不是感觉越来越卡?别急,今天就来教你怎么给安卓机清理系统内存,让你的手机焕发新生!一、内...
安卓子系统要求CPU,安卓子系... 你知道吗?最近在安卓系统圈子里,有个话题可是热得不得了,那就是安卓子系统对CPU的要求。这可不是小事...
安卓系统排名第几,引领智能时代... 你知道吗?在智能手机的世界里,有一个系统可是当之无愧的“王者”——那就是安卓系统!今天,就让我带你一...
阿里云是不是安卓系统,引领安卓... 最近是不是有很多小伙伴在问:“阿里云是不是安卓系统?”这个问题可真是让人好奇啊!咱们就来好好探讨揭开...
安卓系统音量调节的文件,安卓系... 你有没有遇到过这种情况:手机音量调得刚刚好,突然间就变得忽高忽低,让人听得心烦意乱?别急,今天就来跟...
平板刷安卓10原生系统,平板新... 你有没有想过,你的平板电脑也能拥有安卓10的原生系统呢?没错,就是那个流畅又强大的系统,现在它也能在...
安卓系统怎么设定位手机,安卓系... 你有没有想过,你的安卓手机是怎么知道你在哪儿的呢?没错,就是定位功能!这可是现代智能手机的一大亮点,...
升级的安卓系统怎样降级,安卓系... 你有没有遇到过这种情况?手机里的安卓系统突然升级了,结果发现新系统有点小bug,或者某些功能变得不那...
安卓刷机怎么升级系统,轻松实现... 你有没有发现,你的安卓手机最近有点儿慢吞吞的,是不是也想给它来个“大变身”,让它焕发新生呢?没错,刷...
安卓系统迷你小音响,便携式音乐... 你有没有想过,在忙碌的生活中,给自己一个小小的音乐角落,让心情随着音符跳动呢?今天,就让我带你走进一...
老安卓系统怎么删除页面,老安卓... 你有没有发现,手机里的安卓系统用久了,页面上的应用图标就像小山一样堆得高高的?有时候,看着这些图标,...
安卓手机死屏重置系统,轻松解决... 手机突然死屏了,是不是心里一紧?别慌,今天就来跟你聊聊安卓手机死屏后如何重置系统,让你轻松解决这个小...
安卓系统高怎么运行,解锁流畅体... 手机里的安卓系统突然变得卡顿起来,是不是让你感觉像是在迷宫里找出口?别急,今天就来给你支几招,让你的...
安卓系统新消息弹屏,体验升级 你知道吗?最近安卓系统又来了一大波新消息,这可真是让人兴奋不已!想象当你正在专心致志地刷着手机,突然...