(一)正则语法
(1)引入
- 一说规则我已经知道你很晕了
- 首先你要知道的是
- 谈到正则,就只和字符串相关了。
- 在我给你提供的工具中,你输入的每一个字都是一个字符串。
- 其次,如果在一个位置的一个值,不会出现什么变化,那么是不需要规则的。
- 比如
- 你要用"1"去匹配"1"
- 或者用"2"去匹配"2"
- 直接就可以匹配上。
- 这连python的字符串操作都可以轻松做到。
- 那么在之后我们更多要考虑的是在同一个位置上可以出现的字符的范围。
(2)字符组
- 字符组 :[字符组] 在同一个位置可能出现的各种字符组成了一个字符组
- 在正则表达式中用[]表示
- 字符分为很多类
- 假如你现在要求一个位置"只能出现一个数字"
- 那么这个位置上的字符只能是0、1、2...9这10个数之一。
正则 |
待匹配字符 |
匹配结果 |
说明 |
[0123456789] |
8 |
True |
在一个字符组里枚举合法的所有字符,字符组里的任意一个字符和"待匹配字符"相同都视为可以匹配 |
[0123456789] |
a |
False |
由于字符组中没有"a"字符,所以不能匹配 |
[0-9] |
7 |
True |
也可以用-表示范围,[0-9]就和[0123456789]是一个意思 |
[a-z] |
s |
True |
同样的如果要匹配所有的小写字母,直接用[a-z]就可以表示 |
[A-Z] |
B |
True |
[A-Z]就表示所有的大写字母 |
[0-9a-fA-F] |
e |
True |
可以匹配数字,大小写形式的a~f,用来验证十六进制字符 |
import re
"""re.findall(正则模式, 文本) 基于正则模式查找所有匹配的文本内容"""
ret1 = re.findall("a", "a,b,c,d,e")
ret1 = re.findall(".", "a,b,c,d,e")
ret1 = re.findall("[ace]", "a,b,c,d,e")
ret1 = re.findall("[a-z]", "a,b,c,d,e")
ret1 = re.findall("[0-9]", "1,2,3,4,5")
ret1 = re.findall("\d", "1,2,3,4,5")
ret1 = re.findall("[0-9a-z]", "1,a,2,b,3")
ret1 = re.findall("[^a-z]", "1,a,2,b,3")
ret1 = re.findall("[^0-9,]", "1,a,2,b,3")
print(ret1)
(3)元字符
元字符 |
匹配内容 |
. |
匹配除换行符以外的任意字符 |
\w |
匹配字母或数字或下划线 |
\s |
匹配任意的空白符 |
\d |
匹配数字 |
\n |
匹配一个换行符 |
\t |
匹配一个制表符 |
\b |
匹配一个单词的结尾 |
^ |
匹配字符串的开始 |
$ |
匹配字符串的结尾 |
\W |
匹配非字母或数字或下划线 |
\D |
匹配非数字 |
\S |
匹配非空白符 |
a|b |
匹配字符a或字符b |
() |
匹配括号内的表达式,也表示一个组 |
[...] |
匹配字符组中的字符 |
[^...] |
匹配除了字符组中字符的所有字符 |
ret2 = re.findall("[0-9a-zA-Z]", "apple,banana,orange,melon")
ret2 = re.findall("\w", "apple,banana,orange,melon")
ret2 = re.findall("\w+", "apple,banana,orange,melon")
ret2 = re.findall("\w+?", "apple,banana,orange,melon")
ret2 = re.findall("\w*", "apple,banana,orange,melon")
ret2 = re.findall("\w{6}", "apple,banana,orange,melon")
(4)量词
量词 |
用法说明 |
* |
重复零次或更多次 |
+ |
重复一次或更多次 |
? |
重复零次或一次 |
{n} |
重复n次 |
{n,} |
重复n次或更多次 |
{n,m} |
重复n到m次 |
(5)位置元字符. ^ $
正则 |
待匹配字符 |
匹配 结果 |
说明 |
海. |
海燕海娇海东 |
海燕海娇海东 |
匹配所有"海."的字符 |
^海. |
海燕海娇海东 |
海燕 |
只从开头匹配"海." |
海.$ |
海燕海娇海东 |
海东 |
只匹配结尾的"海.$" |
ret3 = re.findall("^\w{5}", "apple,banana,peach,orange,melon")
ret3 = re.findall("\w{5}$", "apple,banana,peach,orange,melon")
ret3 = re.findall("^\w{5}$", "apple,banana,peach,orange,melon")
print(ret3)
(6)重复匹配\* + ? { }
正则 |
待匹配字符 |
匹配 结果 |
说明 |
李.? |
李杰和李莲英和李二棍子 |
李杰 李莲 李二 |
?表示重复零次或一次,即只匹配"李"后面一个任意字符 |
李.* |
李杰和李莲英和李二棍子 |
李杰和李莲英和李二棍子 |
*表示重复零次或多次,即匹配"李"后面0或多个任意字符 |
李.+ |
李杰和李莲英和李二棍子 |
李杰和李莲英和李二棍子 |
+表示重复一次或多次,即只匹配"李"后面1个或多个任意字符 |
李.{1,2} |
李杰和李莲英和李二棍子 |
李杰和 李莲英 李二棍 |
{1,2}匹配1到2次任意字符 |
- 注意:前面的*,+,?等都是贪婪匹配,也就是尽可能匹配,后面加?号使其变成惰性匹配
(7)字符集[][^]
正则 |
待匹配字符 |
匹配 结果 |
说明 |
李[杰莲英二棍子]* |
李杰和李莲英和李二棍子 |
李杰 李莲英 李二棍子 |
表示匹配"李"字后面[杰莲英二棍子]的字符任意次 |
李[^和]* |
李杰和李莲英和李二棍子 |
李杰 李莲英 李二棍子 |
表示匹配一个不是"和"的字符任意次 |
[\d] |
456bdha3 |
4 5 6 3 |
表示匹配任意一个数字,匹配到4个结果 |
[\d]+ |
456bdha3 |
456 3 |
表示匹配任意个数字,匹配到2个结果 |
(8)分组匹配 ()与 或 |[^]
- 身份证号码是一个长度为15或18个字符的字符串
- 如果是15位则全部🈶️数字组成,首位不能为0;
- 如果是18位,则前17位全部是数字,末位可能是数字或x,
- 下面我们尝试用正则来表示:
正则 |
待匹配字符 |
匹配 结果 |
说明 |
^[1-9]\d{13,16}[0-9x]$ |
110101198001017032 |
110101198001017032 |
表示可以匹配一个正确的身份证号 |
^[1-9]\d{13,16}[0-9x]$ |
1101011980010170 |
1101011980010170 |
表示也可以匹配这串数字,但这并不是一个正确的身份证号码,它是一个16位的数字 |
^[1-9]\d{14}(\d{2}[0-9x])?$ |
1101011980010170 |
False |
现在不会匹配错误的身份证号了 ()表示分组,将\d{2}[0-9x]分成一组,就可以整体约束他们出现的次数为0-1次 |
`^([1-9]\d{16}[0-9x] |
[1-9]\d{14})$` |
110105199812067023 |
110105199812067023 |
ret4 = re.findall(",\w{5},", ",apple,banana,peach,orange,melon,")
ret4 = re.findall(",(\w{5}),", ",apple,banana,peach,orange,melon,")
ret4 = re.findall("\w+@\w+\.com", "123abc@163.com,....234xyz@qq.com,....")
ret4 = re.findall("(\w+)@qq\.com", "123abc@163.com,....234xyz@qq.com,....")
ret4 = re.findall("(?:\w+)@(?:qq|163)\.com", "123abc@163.com,....234xyz@qq.com,....")
print(ret4)
(9)转义符\
- 在正则表达式中,有很多有特殊意义的是元字符
- 比如\n和\s等
- 如果要在正则中匹配正常的"\n"而不是"换行符"就需要对""进行转义,变成''。
- 在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。
- 所以如果匹配一次"\n",字符串中要写成'\n',那么正则里就要写成"\n",这样就太麻烦了。
- 这个时候我们就用到了r'\n'这个概念,此时的正则是r'\n'就可以了。
正则 |
待匹配字符 |
匹配 结果 |
说明 |
\n |
\n |
False |
因为在正则表达式中\是有特殊意义的字符,所以要匹配\n本身,用表达式\n无法匹配 |
\n |
\n |
True |
转义\之后变成\,即可匹配 |
"\n" |
'\n' |
True |
如果在python中,字符串中的''也需要转义,所以每一个字符串''又需要转义一次 |
r'\n' |
r'\n' |
True |
在字符串之前加r,让整个字符串不转义 |
""" \b 1个单词边界原子 """
txt = "my name is nana. nihao,nana"
ret = re.findall(r"na", txt)
ret = re.findall(r"\bna", txt)
ret = re.findall(r"\bna\w{2}", txt)
print(ret)
(10)贪婪匹配
- 贪婪匹配:在满足匹配时,匹配尽可能长的字符串,默认情况下,采用贪婪匹配
正则 |
待匹配字符 |
匹配 结果 |
说明 |
<.*> |
<script>...<script> |
<script>...<script> |
默认为贪婪匹配模式,会匹配尽量长的字符串 |
<.*?> |
r'\d' |
<script> <script> |
加上?为将贪婪匹配模式转为非贪婪匹配模式,会匹配尽量短的字符串 |
- 几个常用的非贪婪匹配,Pattern
- *? 重复任意次,但尽可能少重复
- +? 重复1次或更多次,但尽可能少重复
- ?? 重复0次或1次,但尽可能少重复
- {n,m}? 重复n到m次,但尽可能少重复
- {n,}? 重复n次以上,但尽可能少重复
(11)
.
是任意字符
*
是取 0 至 无限长度
?
是非贪婪模式。
- 合在一起就是取尽量少的任意字符,一般不会这么单独写
- 他大多用在:
.*?
就是取前面任意长度的字符,直到一个x出现
(11)模式修正符
- 模式修正符,也叫正则修饰符,模式修正符就是给正则模式增强或增加功能的。
值 |
说明 |
re.I |
是匹配对大小写不敏感 |
re.L |
做本地化识别匹配 |
re.M |
多行匹配,影响到^和$ |
re.S |
使.匹配包括换行符在内的所有字符 |
re.U |
根据Unicode字符集解析字符,影响\w、\W、\b、\B |
re.X |
通过给予我们功能灵活的格式以便更好的理解正则表达式 |
import re
text = """
<12
>
<x
yz>
<!@#$%>
<1a!#
e2>
<>
"""
result_1 = re.findall("<.*?>", text)
result_2 = re.findall("<.*?>", text, re.S)
print(result_1)
print(result_2)
正则语法基础
"""正则语法基础"""
re模块
import re
re模块优先级
"""re模块的优先级"""
res = re.findall('www.(baidu|oldboy).com', 'www.oldboy.com')
print(res)
res = re.findall('www.(?:baidu|oldboy).com', 'www.oldboy.com')
print(res)
start_str = '<span class="content-text" data-count="414" data-index="2"> 早上七点半,昏暗的房间里,松软的大床上,张元清陡然惊醒,捂着头,弓身如虾。</span>'
res = re.compile(pattern=r'<span class="content-text" data-count="414" data-index="2">(.*)</span>')
res = re.findall(pattern=res, string=start_str)
print(res)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)