正则表达式
# 正则表达式
- 正则表达式是匹配类符号
- 正则表达式是一种可以让一些复杂字符串问题变得简单的工具
# 语法一览表
表示法 | 描述 | 正则表达式示例 |
---|---|---|
符号 | ||
literal | 匹配文本字符串的字面值literal | foo |
re1|re2 | 匹配正则表达式re1 或者re2 | foo|bar |
. | 匹配任何字符(除了\n ) | b.b |
^ | 匹配字符串起始部分 | ^Dear |
$ | 匹配字符串终止部分 | /bin/*sh$ |
* | 匹配出现0次或者多次出现的正则表达式 | [A-Za-z0-9]* |
+ | 匹配出现1次或者多次出现的正则表达式 | [a-z]+\.com |
? | 匹配出现0次或者1次出现的正则表达式 | goo? |
{N} | 匹配N次前面出现的正则表达式 | [0-9]{3} |
{M,N} | 匹配出现M~N次出现的正则表达式M,N中间不能有空格 | [0-9]{5,9} |
[...] | 匹配来自字符集中任意单一字符 | [aeiou] |
[...x-y...] | 匹配x-y 范围中的任意单一字符 | [0-9] , [A-Za-z] |
[^...] | 不匹配此字符集中出现的任何一个字符包括某一范围的字符 | [^aeiou] ,[^A-Za-z0-9] |
(*|+|?|{})? | 用于匹配上面频繁出现/重复出现符号的非贪婪版本*、+、?、{} | .*?[a-z] |
(...) | 匹配封闭的正则表达式,然后另存为子组 | ([0-9]{3})?,f(oo|u)bar |
特殊字符 | ||
\d \ | 匹配任何十进制数字与[0-9] 一致 | data\d.txt |
\w | 匹配任何字母数字字符与[A-Za-z0-9_] 一致 | [A-Za-z]\w+ |
\s | 匹配任何空格字符与[\n\t\r\v\f] 一致 | |
\b | 匹配任何单词边界与\B 相反 | \bthe\b |
\N | 匹配已保存的子组N | price: \16 |
\c | 逐子匹配任何特殊字符c | \.,\\,\* |
\A(\Z) | 匹配字符串的起始 | \ADear |
扩展表示法 | ||
?ilLmisux | ||
(?:...) | 表示匹配一个不用保存的分组 | |
(?P<name>) | 像一个仅由name表示而不是数字ID标识的正则分组匹配 | (?P<date>) |
(?P=name) | 在同一字符串中匹配由(?p<name>) 分组的之前文本 | (?P=data) |
(?#...) | 表示注释, 所有内容都被忽略 | (?#comment) |
(?=...) | 匹配条件是如果...出现在之后的位置,而不使用输入字符串;称作正向前视断言 | (?=.com) |
(?!...) | 匹配条件是如果...不出现在之后的位置,而不使用输入字符串;称作负向前视断言 | (?!.net) |
(?<=...) | 匹配条件是如果...出现在之前的位置,而不使用输入字符串;称作正向后视断言 | (?<=800-) |
(?<!...) | 匹配条件是如果...不出现在之前的位置,而不使用输入字符串;称作负向后视断言 | (?<!...192\.168\.) |
(?(id/name)Y|N) | 如果分组提供的id或者name存在,就返回正则表达式的条件匹配Y,如果不存在,就返回N;|N式可选项 | (?(1)Y\|N) |
提示
(?:\w+\.)*
句点作为结尾的字符串,例如google.
、 twitter.
、 facebook.
,但是这些匹配不会保存下来供后续使用和数据检索
(?=.com)
如果一个字符串后面跟着.com
才做匹配操作,并不使用任何目标字符串
(?!.net)
如果一个字符串后面不是跟着.net
才做匹配操作
(?<=800-)
如果一个字符串之前是800-
才做匹配, 假定未电话号码,同样,并不使用任何输入字符串
(?<!192\.|168\.)
如果一个字符串之前不是192.168.
才可以做匹配操作,假定用于过滤一组C类IP地址
(?(\1)y|x)
如果一个匹配组1(\1)存在,就与y匹配;否则,就与x匹配
注意
在符号(?=...)
中加入一个表达式,它就是一个先行断言,用以说明圆括号内的表达式必须正确匹配。比如:/Java(?=\:)/
只能匹配Java且后面有冒号的。
# 语法示例
# 匹配类符号
# 普通符号(字符)
import
result = re.match(r'abc', abc)
2
# . 匹配任意一个字符
result = re.mtch(r".bc", 'abc')
# \d匹配任意一个数字字符
result = re.match(r'x\dy', 'x7y')
# \s匹配任意一个空白字符
result = re.match(r'x\s\y', x\ny)
# \D匹配任意一个非数字
result = re.match(r'x\Dy', 'xmy')
# \S匹配任意一个非空白字符
result = re.match(r'x\Sy', 'xmy')
# 字符集-匹配字符集中的任意字符
v[mnab]
- 匹配m或者n或者a或者b[\dmn]
、[m\dn]
- 匹配任意数字或者m或者n[\d\s]
- 匹配任意数字或者任意空白[1-9]
- 匹配1到9中任意数字[0-9]
- 和\d效果一样[a-z]
- 匹配任意一个小写字母[1-5a-z]
- 匹配数字1到5或者任意小写字母[A-Za-z]
- 匹配任意一个字母[\u4e00-\u9fa5]
- 匹配任意一个中文[\u4e00-\u9fa5wp]
- 匹配任意一个中文或者w或者p
result = re.match(r'x[Mn3+]y', 'xMy')
print(result)
result = re.match(r'x[\u4e00-\u9fa5\dwp]y', 'x3y')
print(result)
2
3
4
5
# [^字符集]-匹配不在字符集中的任意字符
result = re.match(r'x[^mn]y', 'x-y')
print(result)
2
3
# 控制次数符号
# * 0次或者无数次
- * 任意次数 :a* 出现0次或者多次a
- \d* :任意数字出现0次或者多次
- [abc]*:[abc]出现0次或者多次
print(re.match(r'xa*y', 'xy'))
print(re.match(r'xa*y', 'xay'))
print(re.match(r'xa*y', 'xaaaay'))
print(re.match(r'x\d*y', 'xy'))
print(re.match(r'x\d*y', 'x323232312y'))
#<re.Match object; span=(0, 2), match='xy'>
#<re.Match object; span=(0, 3), match='xay'>
#<re.Match object; span=(0, 6), match='xaaaay'>
#<re.Match object; span=(0, 2), match='xy'>
#<re.Match object; span=(0, 11), match='x323232312y'>
2
3
4
5
6
7
8
9
10
11
12
# + 1次或者多次(至少一次)
print(re.match(r'xa+y', 'xy')) # None
print(re.match(r'xa+y', 'xay'))
print(re.match(r'xa+y', 'xaaaay'))
2
3
# ?0次或者1次
print(re.match(r'[+-]?[1-9]\d\d', '810'))
print(re.match(r'9?xy', '9xy'))
2
# {n}次
- {n} n次
- {m, n} m-n次
- {m, } 至少m次
- {,n} 至多n次
print(re.match(r'1[3-9]\d{9}', '13123456789'))
print(re.match(r'1[3-9]\d{1,2}', '1345'))
print(re.match(r'1[3-9]\d{5,}', '131234567'))
print(re.match(r'1[3-9\d{, 3}]', '13123'))
2
3
4
# 分组
整体操作:将正则的一部分用()括起来表示一个分组,然后整体控制次数
重复匹配结果: 在正则中用()添加分组,然后在正则用 \M 来重复它前面第M个分组的匹配结果
捕获:
findall
函数在正则表达式中有分组的时候,只获取分组匹配到的结果
# 只有一个分组的情况
patt = "\w+@(\w.)?\w+\.com"
m = re.match(patt, 'nobody@xxx.com')
print(m.group()) # nobody@xxx.com
patt = "\w+@(\w+\.)*\w+\.com"
m = re.match(patt, "nobody@www.xxxx.yyy.zzz.com")
print(m.group()) # nobody@www.xxxx.yyy.zzz.com
# 多个分组的情况
patt = "\w\w\w-\d\d\d"
m = re.match(patt, "abc-123")
print(m.group()) # abc-123
patt = "(\w\w\w)-(\d\d\d)"
m = re.match(patt, "abc-124")
print(m.groups()) # ('abc', '124')
print(m.group(1)) # abc
print(m.group(2)) # 124
m = re.match("ab", "ab") # 没有子组
print(m.group()) # ab
print(m.groups()) # ()
m = re.match("(ab)", "ab") # 有一个子组
print(m.group()) # 完整匹配 ab
print(m.group(1)) # 子组1 ab
print(m.groups()) # 全部子组("ab",)
m = re.match("(a)(b)", "ab")
print(m.group()) # 完整匹配 ab
print(m.group(1)) # 子组1
print(m.group(2)) # 子组2
print(m.groups()) # 所有子组(a,b)
m = re.match("(a(b))", "ab")
print(m.group()) # 完整匹配ab
print(m.group(1)) #子组1 ab
print(m.group(2)) # 子组2 b
print(m.groups()) ("ab", "b")
# 重复匹配
print(fullmatch(r'([a-z]{2}\d{2})+', 'an23an23km78an23an23'))
print(fullmatch(r'(ab){3}', 'ababab'))
#<re.Match object; span=(0, 20), match='an23an23km78an23an23'>
#<re.Match object; span=(0, 6), match='ababab'>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 分支
- 正则1|正则2|正则3
- 注意:如果是正则的部分要进行分支选择,需要将部分分支地方加()
# abc12、abcMK、abc29、abcTY
print(fullmatch(r'abc\d{2}|abc[A-Z]{2}', 'abc89'))
print(fullmatch(r'abc(\d{2}|[A-Z]{2})', 'abcKS'))
2
3
# 检测类符号
# 单词边界\b
m = re.search(r"\bthe", "bite the dog")
print(m.group()) # "the"
m = re.search(r"\bthe", "bitethe dog") # 匹配失败,the不在边界
print(m ) # None
m = re.search(r"\Bthe", "bitethe dog") # 没有边界
print(m.group()) # the
2
3
4
5
6
# 字符串开头^
m = re.search("^The", "The end")
print(m.group()) #The
m = re.search("^The", "end. The")
print(m) # None
2
3
4
# 字符串结尾$
m = re.search("cat$","this is cat")
# 贪婪匹配和非贪婪匹配
- 贪婪匹配:正则表达式引擎设试图”吸收“匹配该模式尽可能多的字符
- 非贪婪匹配:如果可能就在当前的正则表达式中尽可能少的匹配字符,留下尽可能多的字符给后面的模式
- 贪婪匹配量词,也叫优先匹配量词
{m,n}、{m,}、?、*、+
- 非贪婪匹配符:在贪婪匹配两次后面加一个
?
例如*?、+?、{m,n}?
- 寻找由三个连字符分隔的整数
# 1.使用search验证正则表达式的正确性
patt = "\d+-\d+-\d"
str1 = "Thu Feb 15 17:46:04 2024::uzifzf@dpyivihw.gov::1171590364-6-8"
m = re.search(patt, str1)
print(m) # <re.Match object; span=(47, 61), match='1171590364-6-8'>
# 2.但是使用match,下面匹配失败,因为匹配是从字符串的起始部分开始,需要被匹配的数值位于字符串的末尾
m = re.match(patt, str1)
print(m) # None
# 3.下面正则匹配到结果是整行,但是我们只是需要最后的数字, 不符合要求
patt= ".+\d+-\d+-\d+"
m = re.match(patt, str1)
# <re.Match object; span=(0, 61), match='Thu Feb 15 17:46:04 2024::uzifzf@dpyivihw.gov::11>
# 4. 为了只是获取到题目中的要求,我们加入分组
patt = ".+(\d+-\d+-\d+)"
m = re.match(patt, str1)
print(m.group(1)) # 4-6-8
# 5. 由4可以看到少了数字前面的部分,发生了什么?我们要提取1171590364-6-8 而不是4-6-8
# 问题在于正则表达式本质上是贪婪匹配,这就是说对于该通配模式,将对正则表达式从左向右按顺序求值,而且试图获取该模式的尽可能多的字符
# .+获取从字符串起始位置开始的全部单个字符,包括期望的一个个证书字段。\d仅仅需要一个数字,因此得到"4"
# 6.使用非贪婪标识符改进
patt = ".+?(\d+-\d+-\d)"
m = re.match(patt, str1)
print(m.group(1)) # 1171590364-6-8
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# re模块
- fullmatch(正则, 字符串) - 完全匹配;判断整个字符串是否正则描述的规则,如果不满足结果是None,满足返回匹配对象
- match(正则, 字符串) - 匹配字符串开头;如果不匹配返回None,否则返回匹配对象
- search(正则, 字符串) - 在整个字符串中查找第一个满足正则表达式的子串,如果找不到返回None,否则返回匹配对象
- findall(正则, 字符串) - 获取整个字符串中所有满足正则的子串,返回一个列表 (注意分组问题)
- finditer(正则, 字符串) - 获取整个字符串中所有满足正则的子串,返回一个迭代器,迭代器中的元素是匹配对象
- sub(正则, 字符串1, 字符串2) - 将字符串2中所有满足正则的字串全部替换成字符串1
- split(正则, 字符串) - 将字符串中所有满足正则的子串作为切割点对字符串进行切割
print(fullmatch(r'\d{3}', '123'))
print(match(r'\d{3}', '123阿萨德发234234asfas'))
print(search(r'\d{3}', '阿萨892德发208asf1023as'))
print(findall(r'\d{3}', '阿萨892德发208asf1023as'))
print(findall(r'[a-z](\d{3})', '阿萨892德发208asf1023as'))
str1 = 'how are you? i am fine! thank you! and you?'
result = str1.replace('you', 'me')
print(result)
result = sub(r'you|i', 'me', str1)
print(result)
str1 = '阿萨892德发208asf1023as'
result = sub(r'\d', '*', str1)
print(result)
str1 = 'how are you? i am fine! thank you! and you?'
print(str1.split('you'))
print(split(r'you', str1))
str1 = 'hsj+23g-shdf-ahsf-水电费+234'
print(split(r'[+-]', str1, 2))
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 例题
# 用户名匹配
- 要求: 用户名只能包含数字字母下划线
- 不能以数字开头
- 长度在6-16位
print(re.match("[A-Za-z_][A-Za-z0-9_]{5,15}", "weare_family9339"))
print(re.match(r"^[A-Za-z_][\w]{5,15}$", "weare_family9339"))
print(re.match(r'^[a-zA-z_]\w{5,15}$', "weare_family9339"))
#<re.Match object; span=(0, 16), match='weare_family9339'>
#<re.Match object; span=(0, 16), match='weare_family9339'>
#<re.Match object; span=(0, 16), match='weare_family9339'>
2
3
4
5
6
# 密码匹配
- 不能包含!@#¥%^&*这些特殊符号
- 必须以字母开头
- ⻓度在 6 到 12 位范围内
re.match("^[A-Za-z][^\!@#¥%\^&\*]\w{5,11}", "s123!56") # None
print(re.match("^[A-Za-z][^\!@#¥%\^&\*]\w{5,11}", "s1234w56")) # <re.Match object; span=(0, 8), match='s1234w56'>
2
# 匹配邮箱地址
email = "example@163.com.cny"
m = re.match(r"^[0-9a-zA-Z_]+@[0-9a-zA-Z_]+(\.[0-9a-zA-Z_]+)+", email)
print(m)
2
3
# 匹配手机号码
phone = "15421040384"
m = re.match(r"^1[3-9]\d{9}$", phone)
print(m)
2
3
# 匹配身份证号码
ID = "12345678912345678x"
m = re.match(r"[1-9]{17}[\dXx]$", ID)
print(m)
2
3
4
# 匹配url
url = "http://www.baidu.com.fdfdf"
m = re.match(r"^(http|https)://\w+(\.\w+)+", url)
print(m)
2
3
# ipv4 格式的 ip 地址匹配
IP
地址的范围是 0.0.0.0 - 255.255.255.255
m = re.match(r"(?P<IP>(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)$)", str1)
# m = re.match(r"(?P<IP>((?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d))", "192.168.0.0")
print(m)
print(m.groups("IP"))
2
3
4
# 提取用户输入数据中的数值
- 数值包括正负数 还包括整数和小数在内
- 求和
str1 = '309good87nice19bye'
result = re.search(r"(?P<num>[+\-]*\d+.?\d*\d)", str1)
print(result.group("num"))
2
3
# 输入内容只能是汉字
m = re.match(r'[\u4e00-\u9fa5]+', '测试')
# 匹配整数或者小数
m = re.match(r'[+-]?\d+[.]?\d*', '0')
# 验证用户名和qq号是否有效,并给出对应的提示
- 用户名必须由字母、数字或下划线构成且长度在6~20个字符之间
- QQ号是5~12的数字且首位不能为0
username = input('请输入用户名')
qq = input('请输入qq号码')
m = re.match(r"\w{6,20}", username)
m = re.match(r"[1-9]\d{4,11}", qq)
2
3
4
5
# 提取一首诗中的每一句话
poem = "窗前明月光,疑是地上霜。举头望明月,低头思故乡。"
m = re.split(r"[,。]", poem)
print(m)
2
3
# \d,\W,\s,\B,.,*,+,?
分别是什么
\d 表示匹配数字
\w 用于匹配字母,数字或下划线字符
\W 用于匹配所有与\w不匹配的字符
\s 匹配空格符
\b 表示边界
\B 表示不在边界
. 表示匹配任意一个字符
*表示出现任意多次
+表示至少出现一次
?表示最多出现一次
# (?=a)、(?!a)、(?<=a)、(?<!a)
- (?=a) 零宽正向前视断言 该正则匹配某字符前面的位置。
- (?!a)零宽负向前视断言 与上面的(?!a)相反,这个表达式匹配后面没有a字符的位置
- (?<=a)零宽正向后视断言 与(?=a)位置相反,匹配a字符后面的位置
- (?<!a)零宽负向后视断言 与(?!a)位置相反,匹配前面没有a字符的位置
# 什么是贪婪匹配和非贪婪匹配
贪婪模式:在整个表达式匹配成功的前提下,尽可能多的匹配
非贪婪模式:在整个表达式匹配成功的前提下,尽可能少的匹配
属于贪婪模式的量词,也叫做匹配优先量词,包括:
{m,n}、{m,}、?、*和+
在一些使用NFA引擎的语言中,在匹配优先量词后加上“?”,即变成属于非贪婪模式的量词,也叫做忽略优先量词,包括:
{m,n}?、{m,}?、??、*?和+?
# \d{1,2}*
这样的写法对吗?请说明理由
不正确,这是因为所有限定类元字符后只能紧跟?这个限定类元字符,如果紧跟其他限定类元字符则会报错。正确的写法是(\d{1,2})*
# 写出验证用户名的正则表达式
- 用户名只能输入英文、数字和下划线
m = re.match(r"^[A-Za-z0-9_]+$")
m = re.match(r"^\w+")
2
# 验证用户密码,长度在6~18 之间,只能包含英文和数字
m = re.match(r"[A-Za-z0-9]{6,18}", "passwd123")
print(m) # <re.Match object; span=(0, 9), match='passwd123'>
2
# 验证用户密码强度
- 最少6位
- 至少包括1个大写字母
- 至少包括1个小写字母
- 至少包括1个数字
- 至少包括1个特殊字符
patt = "^.*(?=.{6,})(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*?\(\)]).*$"
str1 = "faa8fa3FBcF0@"
m = re.match(patt, str1)
print(m)
# <re.Match object; span=(0, 13), match='faa8fa3FBcF0@'>
2
3
4
5
# 验证密码的合法性
- 密码长度6-12位
- 由数字、小写字母和大写字母组成
- 必须包含两种字符以上
注意
首先想到,由题目里的三类字符两两组合可以由如下几种情况
- 数字小写字母
- 数字大写字母
- 大小写字母
- 数字大小写字母
由上面的分析可以,密码只要匹配到这三种都是符合条件三的
# 数字价格千分位分隔
将123456789变成123,456,789
# 方法一:
str1 = "123456789"
m = re.sub(r"(?!^)(?=(\d{3})+$)", ',', str1)
# 方法二:
m1 = re.sub(r"(?<=\d)(?=(\d{3})+$)", ",", "123456789")
print(m1)
2
3
4
5
6
7
:::
对这个语法的理解,刚开始是觉得匹配到的每三个都会替换为,
, 但是事实没有
有了下面的思考:
?=(\d{3})
表示连续单位整数的前置位(这个位置实际上不知向任何数字,只是代表一个位置,用于插入分隔符号)
?=
的特殊性:由于正向先行断言的存在,这个正则表达式不会改变原始字符串,也不会匹配任何内容。他只是查找一个位置,配置多个字符时会出现异常需要加上$
改变正则查询的位置
:::
# 手机含3-4-4分隔
str1 = "15652533044"
m = re.sub(r"(?=(\d{4})+$)", "-", str1)
print(m)
2
3
# 匹配Email地址
m = re.match(r"[\w-]+@[\w.]*.[A-Za-z]+", "1565253xxx@aaa.bbb.163.com")
print(m)
# <re.Match object; span=(0, 26), match='1565253xxx@aaa.bbb.163.com'>
2
3
# 匹配yyyy-mm-dd格式的日期
m = re.match(r"\d{4}-([0][19]|[1][0-2])-(0[0-9]|[1-2][0-9]|3[0-1])", "2004-09-08")
print(m.group()) # 2004-09-08
2
# 用正则表达式匹配出身份证号中的出生日期
m = re.match(r"\d{6}(?P<year>\d{4})(?P<month>\d{2})(?P<day>\d{2}).*", "640533199509084563")
# 匹配<a <123> <456> a>中的数字
# 第一中方式
m = re.findall(r"<(\d+)>", "<a <123> <456> a>")
print(m) # ['123', '456']
#第二种方式,利用正向前视断言后正向后视断言
m = re.findall("(?<=\<)\d+(?=\>)", "<a <123> <456> a>")
print(m) # ['123', '456']
2
3
4
5
6
# 匹配以下HTML中的URL
import re
str1 = "<link rel=“search” href=“https://www.baidu.com” />(?<=href=\s?“).*?(?=”\s?/>)"
m = re.findall("(?<=href=“).*(?=” />)", str1)
print(m) # ['https://www.baidu.com']
2
3
4
5
# 匹配以.com结尾的web域名
import re
str1 = "wwww.baidu.com lianxinag.aaaa.com xyzefd.bbb.cccc.dad.com"
m = re.findall("((?:\w+\.)*\w+\.com)", str1)
print(m)
# ['wwww.baidu.com', 'lianxinag.aaaa.com', 'xyzefd.bbb.cccc.dad.com']
2
3
4
5
# 匹配一下html中的文本信息
<!DOCTYPE html>
<html>
<head>
<title>徐清风</title>
<head>
<body>
<h2>
<a>微信公众号:
<em>转行学数据分析</em>
</a>
</h2>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
m = re.findall('(((?<=\<title>)).+(?:(?=\</title>)))|((?<=\<a>).+)|((?<=\<em>).+(?=\</em>))', str1)
# m = re.findall("((?<=\<a>).+)", str1)
# m = re.findall("((?<=\<em>).+(?=\</em>))", str1)
print(m) # [('徐清风', '', ''), ('', '微信公众号: ', ''), ('', '', '转行学数据分析')]
2
3
4
# 在一个目标字符串中,查找两个重复出现的单词
str1 = 'today today is a beautiful day day'
m = re.findall(r"\b([A-Za-z]+)\s+\1\b", str1) # \1是表示引用第一个子分组
print(m) # ['today', 'day']
2
3
# 匹配句子中的日期并且转换输出格式
- 句子中的日期格式
2024-03-02 15:01:00
- 转换为
2024年03月02日15时01分00秒
import datetime
str1 = "this time is {nowtime}".format(nowtime=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
regex = r"((\d{4})-(\d{2})-(\d{2})) ((\d{2}):(\d{2}):(\d{2}))"
subst = r"\2年\3月\4日 \6时\7分\8秒"
m = re.sub(regex, subst, str1)
print(m)
2
3
4
5
6
# 字符串首字母转换为大写,其他为小写
# 方法一
def MatchToUppere(match):
print(match.group())
return match.group().upper()
capitalized = re.sub(r"(\b\w)", MatchToUppere,name)
print(capitalized)
# 方法二
capitalized = re.sub(r"(\b\w)", lambda match:match.group().upper(), name)
2
3
4
5
6
7
8
9
10
# 正则匹配AABB
类型和ABAB
类型的成语
text = '''行尸走肉、金蝉脱壳、百里挑一、金玉满堂、
背水一战、霸王别姬、天上人间、不吐不快、海阔天空、
情非得已、满腹经纶、兵临城下、春暖花开、插翅难逃、
黄道吉日、天下无双、偷天换日、两小无猜、卧虎藏龙、
珠光宝气、簪缨世族、花花公子、绘声绘影、国色天香、
相亲相爱、八仙过海、金玉良缘、掌上明珠、皆大欢喜、
浩浩荡荡、平平安安、秀秀气气、斯斯文文、高高兴兴'''
# m = re.findall(r"(((.)(.)\2\3)|((.)\5(.)\6))", text)
# print(m)
pattern = r'(((.).\3.)|((.)\5(.)\6))'
print("匹配ABAC和AABB的词语:", list(i[0] for i in re.findall(pattern, text)))
2
3
4
5
6
7
8
9
10
11
12
# 使用正则表达式转换文本格式
利用子组引用的方式
# 给数字前面加两个0
111111111 22222222 转变为 00111111111 00222222222
1
2
3
4
5
str1 = '''
1111
11111
22222222
'''
regex = r"\b(\d+)"
subgex = r"00\1"
m = re.sub(regex, subgex, str1)
print(m)
2
3
4
5
6
7
8
9
10
# 匹配句子中的日期并且转换输出格式
- 句子中的日期格式
2024-03-02 15:01:00
- 转换为
2024年03月02日15时01分00秒
str1 = "2024-07-12"
regex = r"((\d{4})-([01][1-9])-([0-3][0-9]))"
subst = r"\2.\3.\4"
m = re.sub(regex, subst, str1)
print(m)
2
3
4
5