目录
1,特殊符号
1-1, 管道符(|)
通过管道符(|), 分割多个正则表达式
# 表示两个正则表达式,一个为at, 另外一个为home
at|home
1-2, 点号(.)
通过点号(.)匹配任意单个字符,换行符除外
# 其中的"."可以匹配任意单个字符,换行符除外
f.o
1-3, 字符串边界匹配
1-3-1, 起始匹配(^)
通过\A或者^, 可匹配字符串开头
# 匹配以From开始的字符串
^From
\AFrom
1-3-2, 结尾匹配($)
通过\Z或者$, 可匹配字符串结尾
# 匹配以/bin/tcsh结束的字符串
/bin/tcsh$
/bin/tcsh\Z
1-3-3, 匹配^, $
通过\^, 可匹配字符^, 通过\$, 可匹配$
# 匹配^的字符串
\^
# 匹配$的字符串
\$
1-4, 单词边界匹配
1-4-1, 单词边界匹配(\b)
通过\b, 单词边界匹配
# 匹配以the开始的字符串
\bthe
1-4-2, 单词中匹配(\B)
通过\B, 单词中的子串匹配
# 匹配包含the的字符串, 单不能以the开头
\Bthe
1-5, 中括号([])
通过[字符1字符2字符3...], 匹配指定字符集中的任意一个
# 表示三个正则表达式:a,b,c
# 表示匹配a,b,c中任意一个字符
[abc]
1-6, 指定范围和否定(-, ^, [])
[a~z]:表示匹配a~z之间的任意一个字符
[^a~z]:表示匹配除a~z以外的任意字符
2, 特殊字符
2-1, 数字匹配
2-1-1, 数字匹配(\d)
通过\d, 匹配数字0~9中的任意数字
# 表示匹配数据0~9, 等价[0-9]
\d
2-1-2, 非数字匹配(\D)
通过\D, 匹配除0~9以外的非数字字符
# 表示匹配除0~9以外的字符
\D
2-2, 字符数字匹配
2-2-1, 字符数字匹配(\w)
通过\w, 匹配0~9,a~z, A~Z, _
2-2-2, 非字符数字匹配(\w)
通过\W, 匹配0~9,a~z, A~Z, _以外的字符
2-3, 空格匹配(\s, \S)
2-3-1, 空格匹配
通过\s, 匹配空格
2-3-2, 非空格匹配
通过\S, 匹配非空格
2-4, 多次匹配(*, +, ?, {})
2-4-1, 问号(?)
2-4-1-1, 匹配0次或1次
单独使用时,表示?前面的字符只能出现0次或1次
# 这里的?,表示t可以出现0次或1次
bat?
2-4-1-2, 非贪婪匹配
紧跟在表示元字符后面,表示非贪婪匹配
2-4-2, 星号(*)
表示星号前面的正则表达式可以出现0次或多次
# 表示\w可以出现0次或多次
\w*
2-4-3, 加号(+)
表示加号前的正则表达式可以出现1次或多次
# 表示\w可出现1次或多次
\w+
2-4-4, 大括号({})
指定大括号前面的表达式出现的次数
# 表示\d出现三次
\d{3}
# 表示\d出现3到5次
\d{3, 5}
2-5, 括号()
通过括号可以实现对正则表达式进行分组,匹配子组
3, re模块
3-1, re.compile()
通过re.compile(正则表达式), 返回一个regex对象,可以提供性能
3-2, group()
通过匹配对象.group(), 返回匹配对象或者根据要求返回子组
In [4]: str1 = 'aatheraa'
In [8]: m = re.search(r'(the)', str1)
# 通过m.group()返回匹配对象
In [9]: m.group()
Out[9]: 'the'
# 通过m.group(1)返回子组1, 1为子组的编号
In [10]: m.group(1)
Out[10]: 'the'
3-3, groups()
通过m.groups(), 可返回子组组成的元组
In [8]: m = re.search(r'(the)', str1)
# 因为r'(the)'只有一个子组,所以返回的元组元素只有一个
In [13]: m.groups()
Out[13]: ('the',)
3-4, re.match()
通过re.match(正则表达式, 字符串), 从字符串的开始进行匹配,成功返回匹配对象,失败则返回None
In [51]: m = re.match('foo', 'foo')
# 匹配成功
In [52]: m
Out[52]: <re.Match object; span=(0, 3), match='foo'>
In [56]: m.group()
Out[56]: 'foo'
3-5, re.search()
通过re.search(正则表达式, 字符串), 从字符串中查询匹配对象,成功返回匹配对象,失败则返回None
# 从整个字符串中进行查找匹配
In [58]: m = re.search('foo', 'seafood')
In [59]: m
Out[59]: <re.Match object; span=(3, 6), match='foo'>
In [60]: m.group()
Out[60]: 'foo'
3-6, re.findall()
通过re.findall(正则表达式, 字符串), 找出所有匹配的部分,返回一个列表
当正则表达式有子组,返回内容是一个元组组成的列表,元组元素是由子组匹配结果组成
# 返回所有匹配部分,是一个列表
In [10]: re.findall('car', 'carry the barcardi to the car')
Out[10]: ['car', 'car', 'car']
# 没有匹配返回一个空列表
In [11]: re.findall('car1', 'carry the barcardi to the car')
Out[11]: []
# 先匹配abc, 通过子组匹配b, 在通过子组匹配c, 所以返回如下
In [17]: m = re.findall('(a(b)(c))', 'abcabc')
In [18]: m
Out[18]: [('abc', 'b', 'c'), ('abc', 'b', 'c')]
3-7, re.sub(), re.subn()
通过re.sub(正则表达式, 字符, my_string, 次数), 匹配my_string中的字符串,通过字符来替换匹配的结果,返回匹配后的字符串, 不指定次数,则表示全部替换, 指定替换次数,则按指定值进行替换
# 没有指定次数替换
In [21]: re.sub('[ae]', 'X', 'abcdef')
Out[21]: 'XbcdXf'
# 按指定次数1次,进行替换
In [22]: re.sub('[ae]', 'X', 'abcdef', 1)
Out[22]: 'Xbcdef'
通过re.subn(正则表达式, 字符, my_string, 次数), 功能和re.sub一样,返回结果是一个元组,指出替换次数
# 没有指定次数,全部替换
In [23]: re.subn('[ae]', 'X', 'abcdef')
Out[23]: ('XbcdXf', 2)
# 按指定次数1次进行替换
In [24]: re.subn('[ae]', 'X', 'abcdef', 1)
Out[24]: ('Xbcdef', 1)
3-8, re.split()
通过re.split(正则表达式), 分割字符串,默认全部分割,也可以指定分割次数, 返回一个列表
# 没有指定次数, 全部分割
In [28]: re.split(r':', 'str1:str2:str3')
Out[28]: ['str1', 'str2', 'str3']
# 按指定次数进行分割
In [19]: re.split(r':', 'str1:str2:str3', 1)
Out[19]: ['str1', 'str2:str3']
4, 正则表达式在python中使用
说明:由于部分特殊字符存在转义的问题,使用正则表达式时,应该用原始字符串
4-1, 匹配多个字符串(|)
# 定义正则表达式, 有三种匹配方式:bat或bet或bit
In [62]: bt = r'bat|bet|bit'
# 通过bat匹配成功
In [63]: m = re.match(bt, 'bat')
In [64]: m.group()
Out[64]: 'bat'
# 通过bet匹配成功
In [67]: m = re.match(bt, 'bet')
In [68]: m.group()
Out[68]: 'bet'
# 通过bit匹配成功
In [69]: m = re.match(bt, 'bit')
In [70]: m.group()
Out[70]: 'bit'
4-2, 匹配任意单个字符(.)
# 点号表示匹配任意单个字符, 换行符除外
In [72]: anyend = r'.end'
# 匹配成功
In [73]: m = re.match(anyend, 'bend')
In [74]: m.group()
Out[74]: 'bend'
# 因为点号不能匹配到换行符,所以这里匹配失败
In [75]: m = re.match(anyend, '\nend')
In [76]: m.group()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[76], line 1
----> 1 m.group()
AttributeError: 'NoneType' object has no attribute 'group'
4-3, 创建字符集合([])
In [81]: m = re.match(r'[cr][23][dp][o2]', 'c3po')
In [82]: m
Out[82]: <re.Match object; span=(0, 4), match='c3po'>
In [83]: m.group()
Out[83]: 'c3po'
4-4, 重复,特殊字符
# (\w+\.)*作用是\w+\.这部分可出现0次或多次
In [84]: pattt = r'\w+@(\w+\.)*\w+\.com'
# www.xxx.yyy对应(\w+\.)出现3次,匹配成功
In [85]: m = re.match(pattt, 'nb@www.xxx.yyy.zzz.com')
In [86]: m.group()
Out[86]: 'nb@www.xxx.yyy.zzz.com'
# (\w+\.)?的作用是\w+\.这部分可出现0次或1次
In [88]: pattt = r'\w+@(\w+\.)?\w+\.com'
# www.xxx对应(\w+\.)出现2次,所以匹配失败
In [91]: m = re.match(pattt, 'nb@www.xxx.yyy.com')
In [92]: m.group()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
Cell In[92], line 1
----> 1 m.group()
AttributeError: 'NoneType' object has no attribute 'group'
# www.对应(\w+\.)出现1次,所以下面的匹配成功
In [93]: m = re.match(pattt, 'nb@www.xxx.com')
In [94]: m.group()
Out[94]: 'nb@www.xxx.com'
4-5, 子组
正则表达式中通过括号可以生成子组
# 无子组情况
In [96]: m = re.match(r'ab', 'ab')
# 返回匹配对象
In [97]: m.group()
Out[97]: 'ab'
# 因为没有子组,所以m.groups()返回一个空元组
In [98]: m.groups()
Out[98]: ()
# 一个子组情况
#(ab)表示正则表达式的一个子组
In [99]: m = re.match('(ab)', 'ab')
# 返回匹配对象
In [100]: m.group()
Out[100]: 'ab'
# 返回指定的子组
In [101]: m.group(1)
Out[101]: 'ab'
# 返回子组构成的元组
In [102]: m.groups()
Out[102]: ('ab',)
# 多个子组情况
# (a)表示一个子组, (b)表示一个子组
In [104]: m = re.match('(a)(b)', 'ab')
# 返回匹配对象
In [105]: m.group()
Out[105]: 'ab'
# 返回子组1
In [106]: m.group(1)
Out[106]: 'a'
# 返回子组2
In [107]: m.group(2)
Out[107]: 'b'
# 返回子组构成的元组
In [108]: m.groups()
Out[108]: ('a', 'b')
# 多个子组情况, 注意,子组的划分是从外到内
In [110]: m = re.match('(a(b))', 'ab')
# 返回匹配对象
In [111]: m.group()
Out[111]: 'ab'
# 返回子组1
In [112]: m.group(1)
Out[112]: 'ab'
# 返回子组1
In [113]: m.group(2)
Out[113]: 'b'
# 返回子组构成的元组
In [114]: m.groups()
Out[114]: ('ab', 'b')
4-6, 字符串的口头或结尾匹配
In [115]: m = re.search(r'^The', 'The end')
# 匹配成功,返回匹配对象
In [116]: m.group()
Out[116]: 'The'
# 因为'end The'不以The开头,所以匹配失败
In [117]: m = re.search(r'^The', 'end The')
In [118]: m
In [126]: m = re.search(r'end$', 'The end')
# 因为字符串'The end'以'end'结尾,所以匹配成功
In [127]: m.group()
Out[127]: 'end'
# 因为字符串'The end1'不以'end'结尾,所以匹配失败
In [128]: m = re.search('end$', 'The end1')
4-7, 单词边界匹配
# '\bthe'搜索字符串中the开始的单词
In [3]: m = re.search(r'\bthe', 'bite the dog')
# 匹配成功
In [4]: m.group()
Out[4]: 'the'
# 字符串中无‘the’开始的单词,所以匹配失败
In [5]: m = re.search(r'\bthe', 'bitethe dog')
In [6]: m
# '\Bthe'表示搜索单词中含有the的部分
In [7]: m = re.search(r'\Bthe', 'bitethe dog')
In [8]: m.group()
Out[8]: 'the'
5, 贪婪匹配&非贪婪匹配
贪婪匹配是正则表达式默认的匹配方法,尽量多的匹配
In [52]: date
Out[52]: 'Wed Aug 9 11:34:23 2023::zslfa@cscwtb.net::1691552063-5-6'
# 由于这里是贪婪匹配
# 其中‘.+’会尽量匹配多的字符,会匹配到‘Wed Aug 9 11:34:23 2023::zslfa@cscwtb.net::169155206’
In [53]: m = re.search(r'.+(\d+-\d+-\d+)', date)
In [54]: m.group(1)
Out[54]: '3-5-6'
非贪婪匹配是在元字符(+, *)后面加上?表示非贪婪匹配,尽量少的匹配
In [55]: date
Out[55]: 'Wed Aug 9 11:34:23 2023::zslfa@cscwtb.net::1691552063-5-6'
# 这里使用非贪婪匹配
# ‘.+?’匹配到‘Wed Aug 9 11:34:23 2023::zslfa@cscwtb.net::’
# 将后面的数字交给\d+进行匹配
In [56]: m = re.search(r'.+?(\d+-\d+-\d+)', date)
In [57]: m.group(1)
Out[57]: '1691552063-5-6'