Python基础之正则表达式

文章目录

  • [1 正则表达式](#1 正则表达式)
    • [1.1 简介](#1.1 简介)
    • [1.2 match和search](#1.2 match和search)
      • [1.2.1 re.match函数](#1.2.1 re.match函数)
      • [1.2.2 re.search方法](#1.2.2 re.search方法)
      • [1.2.3 re.match 与 re.search的区别](#1.2.3 re.match 与 re.search的区别)
    • [1.3 检索和替换](#1.3 检索和替换)
      • [1.3.1 re.sub](#1.3.1 re.sub)
      • [1.3.2 compile](#1.3.2 compile)
      • [1.3.3 findall](#1.3.3 findall)
      • [1.3.4 re.finditer](#1.3.4 re.finditer)
      • [1.3.5 re.split](#1.3.5 re.split)
    • [1.4 正则表达式对象](#1.4 正则表达式对象)
    • [1.5 正则表达式修饰符](#1.5 正则表达式修饰符)
      • [1.5.1 可选标志](#1.5.1 可选标志)
      • [1.5.2 正则表达式模式](#1.5.2 正则表达式模式)

1 正则表达式

1.1 简介

正则表达式是一个特殊的字符序列,它能方便的检查一个字符串是否与某种模式匹配。

在 Python 中,使用 re 模块来处理正则表达式。
re 模块提供了一组函数,允许你在字符串中进行模式匹配、搜索和替换操作。
re 模块使 Python 语言拥有完整的正则表达式功能。

1.2 match和search

1.2.1 re.match函数

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

函数语法:re.match(pattern, string, flags=0)

函数参数说明:

  • pattern:匹配的正则表达式
  • string:要匹配的字符串。
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等

匹配成功 re.match 方法返回一个匹配的对象,否则返回 None

可以使用 group(num)groups() 匹配对象函数来获取匹配表达式。

  • group(num=0):匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
  • groups():返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
py 复制代码
import re
print(re.match('www', 'www.baidu.com').span())  # 在起始位置匹配
print(re.match('com', 'www.baidu.com'))         # 不在起始位置匹配

输出结果为:
(0, 3)
None
py 复制代码
import re
 
line = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
 
if matchObj:
   print ("matchObj.group() : ", matchObj.group())
   print ("matchObj.group(1) : ", matchObj.group(1))
   print ("matchObj.group(2) : ", matchObj.group(2))
else:
   print ("No match!!")

执行结果如下:

matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter

1.2.2 re.search方法

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

函数语法:re.search(pattern, string, flags=0)

函数参数说明:

  • pattern:匹配的正则表达式
  • string:要匹配的字符串。
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等

匹配成功re.search方法返回一个匹配的对象,否则返回None。

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

  • group(num=0):匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
  • groups():返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
py 复制代码
import re
 
print(re.search('www', 'www.baicu.com').span())  # 在起始位置匹配
print(re.search('com', 'www.baidu.com').span())         # 不在起始位置匹配
以上实例运行输出结果为:

(0, 3)
(11, 14)
py 复制代码
import re
 
line = "Cats are smarter than dogs"
 
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
 
if searchObj:
   print ("searchObj.group() : ", searchObj.group())
   print ("searchObj.group(1) : ", searchObj.group(1))
   print ("searchObj.group(2) : ", searchObj.group(2))
else:
   print ("Nothing found!!")

执行结果如下:
searchObj.group() :  Cats are smarter than dogs
searchObj.group(1) :  Cats
searchObj.group(2) :  smarter

1.2.3 re.match 与 re.search的区别

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

py 复制代码
import re
 
line = "Cats are smarter than dogs"
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
   print ("match --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")
 
matchObj = re.search( r'dogs', line, re.M|re.I)
if matchObj:
   print ("search --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")

运行结果如下:
No match!!
search --> matchObj.group() :  dogs

1.3 检索和替换

1.3.1 re.sub

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

语法:re.sub(pattern, repl, string, count=0, flags=0)

  • pattern:正则中的模式字符串。
  • repl:替换的字符串,也可为一个函数。
  • string:要被查找替换的原始字符串。
  • count:模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
  • flags:编译时用的匹配模式,数字形式。

前三个为必选参数,后两个为可选参数。

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

执行结果如下:

电话号码 :  2004-959-559 
电话号码 :  2004959559

repl 参数是一个函数

以下实例中将字符串中的匹配的数字乘以 2:

py 复制代码
import re
# 将匹配的数字乘以 2
def double(matched):
    value = int(matched.group('value'))
    return str(value * 2)
 
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))

输出结果为:
A46G8HFD1134

1.3.2 compile

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

语法格式为:re.compile(pattern[, flags])

  • pattern:一个字符串形式的正则表达式
  • flags:可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
    • re.IGNORECASE 或 re.I:- 使匹配对大小写不敏感
    • re.L:表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
    • re.MULTILINE 或 re.M:多行模式,改变 ^$ 的行为,使它们匹配字符串的每一行的开头和结尾。
    • re.DOTALL 或 re.S:使 . 匹配包括换行符在内的任意字符。
    • re.ASCII:使 \w, \W, \b, \B, \d, \D, \s, \S 仅匹配 ASCII 字符。
    • re.VERBOSE 或 re.X:忽略空格和注释,可以更清晰地组织复杂的正则表达式。

这些标志可以单独使用,也可以通过按位或(|)组合使用。例如, re.IGNORECASE | re.MULTILINE表示同时启用忽略大小写和多行模式。

py 复制代码
import re
pattern = re.compile(r'\d+')                    # 用于匹配至少一个数字
m = pattern.match('one12twothree34four')        # 查找头部,没有匹配
print( m )
None
m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配
print( m )
None
m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配
print( m )                                        # 返回一个 Match 对象
<_sre.SRE_Match object at 0x10a42aac0>
m.group(0)   # 可省略 0
'12'
m.start(0)   # 可省略 0
3
m.end(0)     # 可省略 0
5
m.span(0)    # 可省略 0
(3, 5)

在上面,当匹配成功时返回一个 Match 对象,其中:

  • group([group1, ...]):方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
  • start([group]):方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
  • end([group]):方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
  • span([group]):方法返回 (start(group), end(group))。

再看看一个例子:

py 复制代码
import re
pattern = re.compile(r'([a-z]+) ([a-z]+)', re.I)   # re.I 表示忽略大小写
m = pattern.match('Hello World Wide Web')
print( m )                            # 匹配成功,返回一个 Match 对象
<_sre.SRE_Match object at 0x10bea83e8>
m.group(0)                            # 返回匹配成功的整个子串
'Hello World'
m.span(0)                             # 返回匹配成功的整个子串的索引
(0, 11)
m.group(1)                            # 返回第一个分组匹配成功的子串
'Hello'
m.span(1)                             # 返回第一个分组匹配成功的子串的索引
(0, 5)
m.group(2)                            # 返回第二个分组匹配成功的子串
'World'
m.span(2)                             # 返回第二个分组匹配成功的子串索引
(6, 11)
m.groups()                            # 等价于 (m.group(1), m.group(2), ...)
('Hello', 'World')
>>> m.group(3)                            # 不存在第三个分组
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: no such group

1.3.3 findall

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

注意matchsearch 是匹配一次 findall 匹配所有。

语法格式为:re.findall(pattern, string, flags=0)

pattern.findall(string[, pos[, endpos]])

参数:

  • pattern:匹配模式。
  • string:待匹配的字符串。
  • pos:可选参数,指定字符串的起始位置,默认为 0。
  • endpos:可选参数,指定字符串的结束位置,默认为字符串的长度。
    查找字符串中的所有数字:
py 复制代码
import re
 
result1 = re.findall(r'\d+','test 123 google 456')
pattern = re.compile(r'\d+')   # 查找数字
result2 = pattern.findall('test 123 google 456')
result3 = pattern.findall('te88st123google456', 0, 10)
 
print(result1)
print(result2)
print(result3)
输出结果:

['123', '456']
['123', '456']
['88', '12']

多个匹配模式,返回元组列表:

py 复制代码
import re

result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
print(result)
[('width', '20'), ('height', '10')]

1.3.4 re.finditer

findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
re.finditer(pattern, string, flags=0)

  • pattern:匹配的正则表达式
  • string:要匹配的字符串。
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
py 复制代码
import re

it = re.finditer(r"\d+","12a32bc43jf3") 
for match in it: 
    print (match.group() )
输出结果:

12 
32 
43 
3

1.3.5 re.split

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:re.split(pattern, string[, maxsplit=0, flags=0])

  • pattern:匹配的正则表达式
  • string:要匹配的字符串。
  • maxsplit:分割次数,maxsplit=1 分割一次,默认为 0,不限制次数。
  • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等
py 复制代码
>>>import re
>>> re.split('\W+', 'baidu, baidu, baidu.')
['baidu', 'baidu', 'baidu', '']
>>> re.split('(\W+)', ' baidu, baidu, baidu.') 
['', ' ', 'baidu', ', ', 'baidu', ', ', 'baidu', '.', '']
>>> re.split('\W+', ' baidu, baidu, baidu.', 1) 
['', 'baidu, baidu, baidu.']
 
>>> re.split('a*', 'hello world')   # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['hello world']

1.4 正则表达式对象

re.RegexObject
re.compile() 返回 RegexObject 对象。

re.MatchObject
group() 返回被 RE 匹配的字符串。

  • start():返回匹配开始的位置
  • end():返回匹配结束的位置
  • span():返回一个元组包含匹配 (开始,结束) 的位置

1.5 正则表达式修饰符

1.5.1 可选标志

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。

以下标志可以单独使用,也可以通过按位或(|)组合使用。例如,re.IGNORECASE | re.MULTILINE 表示同时启用忽略大小写和多行模式。

修饰符 描述
re.IGNORECASE 或 re.I 使匹配对大小写不敏感
re.MULTILINE 或 re.M 多行匹配,影响 ^$,使它们匹配字符串的每一行的开头和结尾。
re.DOTALL 或 re.S 使 . 匹配包括换行符在内的任意字符。
re.ASCII 使 \w, \W, \b, \B, \d, \D, \s, \S 仅匹配 ASCII 字符。
re.VERBOSE 或 re.X 忽略空格和注释,可以更清晰地组织复杂的正则表达式。

1.5.2 正则表达式模式

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

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

多数字母和数字前加一个反斜杠时会拥有不同的含义。

标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。

反斜杠本身需要使用反斜杠转义。

由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'\t',等价于 \t )匹配相应的特殊字符。

模式 描述
^ 匹配字符串的开头
$ 匹配字符串的末尾
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...] 用来匹配所包含的任意一个字符,例如 [amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n} 匹配n个前面表达式。例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。
re{ n,} 精确匹配n个前面表达式。例如,"o{2,}"不能匹配"Bob"中的"o",但能匹配"foooood"中的所有o。"o{1,}"等价于"o+"。"o{0,}"则等价于"o*"。
re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b 匹配a或b
(re) 匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 类似 (...), 但是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#...) 注释.
(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功。
(?> re) 匹配的独立模式,省去回溯。
\w 匹配数字字母下划线
\W 匹配非数字字母下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f]。
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9]
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 匹配一个换行符。匹配一个制表符, 等
\1...\9 匹配第n个分组的内容。
\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。
相关推荐
TNTLWT2 小时前
MySQL:设计数据库与操作
数据库·mysql
VX_DZbishe2 小时前
springboot旅游管理系统-计算机毕业设计源码16021
java·spring boot·python·servlet·django·flask·php
青春之我_XP2 小时前
【知识图谱系列】Neo4j使用Py2neo与python进行链接
python·知识图谱·neo4j
IT数据小能手2 小时前
Python中爬虫编程的常见问题及解决方案
开发语言·爬虫·python
橙子味冰可乐2 小时前
isprintable()方法——判断字符是否为可打印字符
java·前端·javascript·数据库·python
Hi202402172 小时前
将数据切分成N份,采用NCCL异步通信,让all_gather+matmul尽量Overlap
pytorch·python·性能优化·分布式训练·nccl·融合算子
凉拌糖醋鱼5 小时前
Python-PDF文件密码破解小工具
开发语言·python·pdf·密码破解
IT数据小能手5 小时前
天猫商品列表数据接口(Tmall.item_search)
大数据·爬虫·python
qqyqqyqqyqqy17 小时前
Mysql的SQL语句实例
数据库·sql·mysql
铁蛋Q7 小时前
linux和mysql基础指令
linux·运维·mysql