目录
1、最常用匹配方式:findall(pattern, string, flags=0)
2、re.match(pattern, string, flags)
5、re.findall(),re.match(),re.search()区别
6、re.sub(pattern, repl, string, count=0, flags=0)
一、什么是正则
正则表达式(regular expression)是一种用于匹配字符串中字符组合的==模式==
特点:
正则表达式的语法很令人头疼,可读性差
正则表达式通用行很强,能够适用于很多编程语言,Java、PHP、Go以及JavaScript等语言中都是支持正则表达式的。
二、常用正则表达式
| 规则 | 实例 |
| ^ | 匹配字符串的开头 |
| $ | 匹配字符串的末尾。 |
| . | 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。 |
| [...] | 用来匹配所包含的任意一个字符,例如 [amk] 匹配 'a','m'或'k' |
| [Pp]ython 匹配 "Python" 或 "python" rub[ye] 匹配 "ruby" 或 "rube" [aeiou] 匹配中括号内的任意一个字母 [0-9] 匹配任何数字。类似于 [0123456789] [a-z] 匹配任何小写字母 [A-Z] 匹配任何大写字母 [a-zA-Z0-9] 匹配任何字母及数字 | |
| [^...] | 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。 |
| [^aeiou] 除了a,e,i,o,u字母以外的所有字符 [^0-9] 匹配除了数字外的字符 | |
| () | 匹配括号内的表达式,也表示一个组 |
| ? | 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式 |
| \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_]'。 |
| 表达式* | 匹配0个或多个的表达式。\w*,(\w* = \d*)* |
| 表达式+ | 匹配1个或多个的表达式。\w+,[a-z]+ |
| 表达式{n} | 匹配前一个字符出现x次 次数==x。 {x,y}:匹配前一个字符出现x到y次 次数>=x 并且 次数<=y 例如,"o{2}"不能匹配"Bob"中的"o",但是能匹配"food"中的两个o。 |
| .* | 匹配任意字符或组(ab123) |
| [^/\s]* | 匹配0个或多个非(/、\s) 字符 |
三、常用方法
1、最常用匹配方式:findall(pattern, string, flags=0)
作用:在字符串中找到正则匹配到的所有结果,并返回一个列表;如果正则有多个匹配模式则返回元组列表;若没有匹配结果,则返回一个空列表
返回值:列表,或元组列表[(a,b),c]
用法:
re.findall(pattern, string, flags=0)
或 pattern.findall(string[, pos[, endpos]])
参数:
-
pattern 匹配模式。
-
string 待匹配的字符串。
-
pos 可选参数,指定字符串的起始位置,默认为 0。
-
endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。
示例:
import re
string = 'wegit=75 Goals=100 99.'
result=re.findall(r'\w+',string) #匹配任意个英文字符或下划线
result1=re.findall(r'(\w+)=(\d+)',string)
pattern=re.compile(r'\w+') #正则表达式模式编译为正则表达式对像,方便重复调用
print(f'result:{result}')
print(f'result1:{result1}')
print(pattern.findall(string))
输出结果:
result:['wegit', '75', 'Goals', '100', '99']
result1:[('wegit', '75'), ('Goals', '100')]
['wegit', '75', 'Goals', '100', '99']
2、re.match(pattern, string, flags)
作用:从参数中string字符串的头进行匹配,若字符串头部不符合条件则直接抛出异常
返回值:返回一个匹配的对象,需要使用使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式
| 参数 | 描述 |
|---|---|
| pattern | 匹配规则,自定义的正则表达式 |
| string | 要匹配的字符串。 |
| flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
import re
string = 'lee wegit=75 goals=100 99.'
result1 = re.match(r'\w*',string)
print(result1.group(0))
输出结果:
lee
代码说明:
因\w匹配包含下划线、英文字符,string中'lee' 之后为空格所以中断匹配
3、group(0)、groups()
a、group()
作用:返回匹配对象的整个匹配结果或特定分组匹配结果
用法:
m.group():返回整个匹配的子字符串(等同于m.group(0))。m.group(n):返回第n个分组匹配的子字符串(n从1开始)。m.group(n1, n2, ...):返回多个分组匹配结果的元组(按顺序返回指定分组)
示例:
import re
string = 'wegit=75 goals=100 99.'
result1 = re.match(r'(\w+)=(\d+)',string)
print(f'group(0):{result1.group(0)}')
print(f'group(1):{result1.group(1)}')
print(f'group(2):{result1.group(2)}')
输出结果:
group(0):wegit=75
group(1):wegit
group(2):75
b、groups()
作用:返回所有分组匹配结果组成的元组
用法:m.groups(),返回一个包含所有分组匹配结果的元组(不包括整个匹配)
示例:
import re
string = 'wegit=75 goals=100 99.'
result1 = re.match(r'(\w+)=(\d+)',string)
print(f'groups():{result1.groups()}')
输出结果:
groups():('wegit', '75')
c、区别
group():返回整个匹配或指定分组(group(0)为整个匹配)。groups():仅返回所有分组匹配结果的元组(不包括整个匹配)。
d、注意点
- 分组编号:分组编号从1开始,
group(0)始终返回整个匹配。 - 捕获组:只有使用括号
()定义的捕获组才会被groups()捕获。 - 错误处理:如果指定的分组编号不存在,会引发
IndexError
4、re.search()
作用:扫描完成字符串、并返回第一个匹配的对象
输出:返回一个匹配的对象,需要使用使用 group(num) 或 groups() 匹配对象函数来获取匹配表达式
用法:re.search(pattern, string, flags=0)
| 参数 | 描述 |
|---|---|
| pattern | 匹配规则,自定义的正则表达式 |
| string | 要匹配的字符串。 |
| flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。 |
示例:匹配域名和路径
def extract_url(input_str):
pattern = r'https?://([^/\s]+)(/\w*)*'
result = re.search(pattern,input_str)
if result:
return result.group(0)
else:
return None
str1 = "123https://www.baidu.com/si/weixin?wd=r%27"
str2 = "123https://www.baidu.com/s?wd=r7"
print(extract_url(str1))
print(extract_url(str2))
输出结果:
https://www.baidu.com/si/weixin
https://www.baidu.com/s
5、re.compile()
作用:生成一个含有指定正则表达式的 正则表达式对象,方便之后重复调用次表达时
返回值:返回一个编译后的正则表达式对象 (re.Pattern)
基本语法:
re.compile(pattern, flags=0)
参数:
pattern: 字符串类型的正则表达式模式。
flags: 可选参数,正则表达式标志(如 re.IGNORECASE, re.MULTILINE 等),可以使用 | 组合多个标志。
代码示例:
pattern = re.compile(r'1[0-9]{10}') # [0-9]{10} 0-9间任意数出现10次
str1 = "dfaer19230511176fasdt"
result = pattern.search(str1)
print(result.group())
6、re.findall(),re.match(),re.search()区别
re.match必须从头开始匹配,如果符合正则表达式,就匹配失败;re.findall()、re.search()是匹配整个字符串,知道找到一个符合条件的
re.findall()的返回值是列表,而re.match()、re.search()的返回值是对象,需要借助group(0)、groups()完成输出
re.findall()可以匹配字符串中多个符合条件的子串,re.search()只返回第一个匹配的对象
7、re.sub(pattern, repl, string, count=0, flags=0)
作用:用指定字符串repl,替换正则匹配到的子串
输出:字符串
用法:re.sub(pattern, repl, string, count=0, flags=0)
repl为空则为删除,删除string中匹配到的字段
参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
- flags : 编译时用的匹配模式,数字形式。
示例:
import re
phone = '2024-10-30 #凤羽 #鸡柳'
results = re.sub(r'#.*',"",phone)
print(results)
# print(result1)
输出结果:
2024-10-30
四、使用场景
1、正则匹配单个字符规则
记忆方式: d:digit数字 s:space空白 w:word词
. : 任意1个字符(除了\n)
[]: 中括号中任意1个字符
\d: 任意1个数字(0-9)
\D: 非数字
\s: 任意1个空白(空格,\t,\n)
\S: 非空白
\w: 任意1个正常词(字母,数字,下划线,汉字)
\W: 非正常词(特殊字符)
str1 = "erwe 414/reqwt"
# 任意1个字符(除了\n)
result0 = re.match(r'.',str1)
get_result(result0)
# 中括号中任意1个字符
result1 = re.match(r'[a-z]',str1)
get_result(result1)
str2 = "12erwe 414/reqwt"
# 任意1个数字(0-9)
result2 = re.match(r'\d',str2)
get_result(result2)
# 非数字
result3 = re.match(r'\D',str1)
get_result(result3)
# 任意1个空白(空格,\t,\n)
result4 = re.match(r'\s',str2)
get_result(result4)
# 非空白
result5 = re.match(r'\S',str2)
get_result(result5)
# 任意1个正常词(字母,数字,下划线,汉字)
result6 = re.match(r'\w',str2)
get_result(result6)
# 非正常词(特殊字符)
result7 = re.match(r'\W',str2)
get_result(result7)
2、正则匹配多个字符规则
* : 匹配前一个字符出现0次或者无限次 次数>=0
.*:匹配任意字符或组(ab123)
\w*:匹配任意个包括下划线的单词字符,等价于'[A-Za-z0-9_]'
+ : 匹配前一个字符出现1次或者无限次 次数>=1
? : 匹配前一个字符出现0次或者1次 次数== 0 或者 次数 == 1
{x}: 匹配前一个字符出现x次 次数==x
{x,y}:匹配前一个字符出现x到y次 次数>=x 并且 次数<=y
import re
def get_result(num):
if num:
print(F"Match Success, result:{num.group()}")
else:
print("Match Fail!")
str1 = "1234315 after noon"
# 匹配\d数次多次
result0 = re.match(r'\d*',str1)
get_result(result0)
# 匹配任意字符(除\n)至少一次
result1 = re.match(r'.+',str1)
get_result(result1)
# 匹配\d两次
result2 = re.match(r'\d{2}',str1)
get_result(result2)
# 匹配\w 至少2次,至多6次
result3 = re.search(r'\w{2,6}', str1)
get_result(result3)
# 匹配\w 0或1次
result4 = re.search(r'\w?', str1)
get_result(result4)
3、正则匹配开头和结尾
^ : 匹配以什么开头
$ : 匹配以什么结尾
注意: ^和$一般都是配合使用,起到限制作用
import re
def get_result(num):
if num:
print(F"Match Success, result:{num.group()}")
else:
print("Match Fail!")
str1="asd123"
# 从头开始匹配,结尾也满足\w可以连续匹配六次的
result = re.match(r'\w{6}$',str1)
get_result(result)
# 头和结尾都满足\w可以连续匹配六次的
result1 = re.search(r'^\w{6}$',str1)
get_result(result1)
4、正则匹配分组
| : 匹配左右任意一个表达式 或者
(?=.*匹配规则1)(?=.*匹配规则1).{x,y} :实现和的概念,须同时满足匹配规则1和2,且总字符串长度次数>=x 并且 次数<=y
(): 小括号中内容为一组,默认产生从1开始的编号
\n: 根据分组编号n引用对应的分组
(?P<name>) : 给分组起别名name
(?P=name) : 根据分组名name引用对应的分组
注意:需要匹配html等前后需要一致的情况时,必须使用分组
分组可以保证前后匹配的字符一致
import re
def get_result(num):
if num:
print(F"Match Success, result:{num.group()}")
else:
print("Match Fail!")
str1 = "<h1>look</h2>" # html语言前后必须一致
result0 = re.match(r'<[h1-6]+>.*</[h1-6]+>', str1)
get_result(result0) # 输出:Match Success, result:<h1>look</h2>
# 使用分组形式进行匹配,可以保证前后一致
str2 = "<h2>look</h2>" # html语言前后必须一致
result1 = re.match(r'<([h1-6]+)>.*</\1>', str2)
get_result(result1) # 输出:Match Success, result:<h2>look</h2>
str3 = "<h2>look</h3>" # 因前后<h2>与<h3>不一致导致匹配失败
# 要求前后必须一致,前边是h1,后边也必须是h1
result2 = re.match(r'<([h1-6]+)>.*</\1>', str3)
get_result(result2) # 输出:Match Fail!
# 为分组添加组名,后边根据组名进行调用
str4 = "<h2>look</h2>"
result4 = re.match(r'<(?P<title1>h[1-6])>.*</(?P=title1)>',str4)
get_result(result4) # 输出:Match Success, result:<h2>look</h2>
str4 = "<h2>look</h3>" # 因前后<h2>与<h3>不一致导致匹配失败
result4 = re.match(r'<(?P<title1>h[1-6])>.*</(?P=title1)>',str4)
get_result(result4) # 输出:Match Fail!
# 检查用户输入的密码是否有效
str5 = "ABd1234@1,a F1#,2w3E*,2We3345,ACe1234@1"
result5 = re.search(r'^(?=.*[a-z])(?=.*[0-9])(?=.*[A-Z])(?=.*[$#@]).{6,12}$', str5)
get_result(result5)
5、特殊匹配
注意: 如果^放到了[]里面,表示取反作用
举例: [^\d] == [\D]
import re
def get_result(num):
if num:
print(F"Match Success,result:{num.group()}")
else:
print("Match Fail!")
str1 = "214 ewr"
result1 = re.match(r'[^/\s]*', str1)
get_result(result1)
五、综合练习
1、提取域名
def get_result(res):
if res:
print(f'Match Successful,{res.group()}')
else:
print("Match fail!")
str1 = "125135https://www.baidu.com/index/fafa/1231%"
result = re.search(r'https?://[^/\s]*',str1) # [^/\s]*非 / 和 空格的所有任意字符
get_result(result)
2、匹配密码必须是数字、字母下划线 且位数为6
import re
def get_result(num):
if num:
print(F"Match Success, result:{num.group()}")
else:
print("Match Fail!")
str1="asd123"
# 从头开始匹配,结尾也满足\w可以连续匹配六次的
result = re.match(r'\w{6}$',str1)
get_result(result)
# 头和结尾都满足\w可以连续匹配六次的
result1 = re.search(r'^\w{6}$',str1)
get_result(result1)
3、匹配html,必须保证前后一致
<h2>look</h2> 前边时h2,后边也必须是h2
import re
def get_result(num):
if num:
print(F"Match Success, result:{num.group()}")
else:
print("Match Fail!")
# 使用分组形式进行匹配,可以保证前后一致
str2 = "<h2>look</h2>" # html语言前后必须一致
result1 = re.match(r'<([h1-6]+)>.*</\1>', str2) # \1 是引用前边的group(1)
get_result(result1) # 输出:Match Success, result:<h2>look</h2>
4、检查用户输入的密码是否有效
网站要求用户输入用户名和密码进行注册。编写程序以检查用户输入的密码是否有效。
以下是检查密码的标准:
[az]之间至少1个字母
[0-9]之间至少1个数字
[AZ]之间至少1个字母
[$#@]中的至少1个字符
交易密码的最小长度:6
交易密码的最大长度:12
您的程序应接受逗号分隔的密码序列,并将根据上述条件进行检查。符合条件的密码将被打印,每个密码之间用逗号分隔。 例子 如果输入以下密码作为程序输入:ABd1234@1,a F1#,2w3E*,2We3345
程序输出结果为: ABd1234@1
import re
def check_password(str1):
list1 = str1.split(",")
list2 = []
for i in list1:
result = re.search(r'^(?=.*[a-z])(?=.*[0-9])(?=.*[A-Z])(?=.*[$#@]).{6,12}$', i)
if result:
list2.append(result.group())
print(list2)
return ",".join(list2)
str1 = "ABd1234@1,a F1#,2w3E*,2We3345,ACe1234@1"
print(check_password(str1))
六、贪婪模式和非贪婪模式
贪婪模式: 在整个表达式匹配成功的前提下,尽可能多的匹配
非贪婪模式: 在整个表达式匹配成功的前提下,尽可能少的匹配
正则中的量词:*和+,默认都是贪婪模式的匹配,可以在他们后面加?将其变为非贪婪模式。
常用贪婪模式如: .* .+
常用非贪婪模式如: .*? .+?
import re
str1 = "<h1>内容1</h1>无用字符<h1>内容二</h1>无用字符<h1>内容二</h1>"
result1 = re.findall(r'<h1>.*?</h1>', str1)
print(result1) # 输出:['<h1>内容1</h1>', '<h1>内容二</h1>', '<h1>内容二</h1>']
# findall如果使用分组,那么只返回分组中的内同
result2 = re.findall(r'<h1>(.*?)</h1>', str1)
print(result2) # 输出:['内容1', '内容二', '内容二']
* 使用注意点:
量词 * 允许“匹配零次”,所以每个不匹配的位置都产出了一个空字符串
下边代码中:'2', '1', '4'数字因为不符合匹配条件但量词 * 允许“匹配零次”,所以每个不匹配的位置都产出了一个空字符串
str3 = "214ewr"
result3 = re.findall(r'[^\d\s]*', str2)
print(result3)
#输出:['', '', '', '', 'ewr', '']
七、正则修饰符
修饰符: 正则表达式可以包含一些可选标志修饰符来控制匹配的模式
常见的修饰符
re.I : 设置当前匹配不区分大小写
re.S : 设置.真正匹配到任意字符包含\n
import re
def get_result(num):
if num:
print(F"Match Success, result:{num.group()}")
else:
print("Match Fail!")
# 忽略大小写
str1 = "sdfaSFER2114"
result = re.match(r'[a-z]+',str1)
get_result(result) # 输出:Match Success, result:sdfa
result1 = re.match(r'[a-z]+', str1, re.I)
get_result(result1) # 输出:Match Success, result:sdfaSFER
# 忽略换行符
str2 = "wqr/nwrqe/nwrq"
result2 = re.match(r'.*', str2)
get_result(result2) # 输出:Match Success, result:wqr/nwrqe/nwrq
result3 = re.match(r'.*', str2, re.S)
get_result(result3) # 输出:Match Success, result:wqr/nwrqe/nwrq

2万+

被折叠的 条评论
为什么被折叠?



