一、正则表达式需要用到的模块和函数
1、导入模块:import re
2、使用模块中的函数:re.match(正则表达式, 要匹配的字符串),re.search(正则表达式, 要匹配的字符串)
import re
def simple():
"""
初识正则表达式
re.rematch(正则表达式, 要匹配的字符串)
:return:
"""
result = re.match("www", "www.baidu.com")
if result:
print(result.group())
if __name__ == '__main__':
simple()
输出结果:
www
二、匹配单个字符
字符 | 功能 |
. | 匹配任意 1 个字符(除了\n) |
[ ] | 匹配[ ]中列举的字符 |
\d | 匹配数字, 即 0-9 decimal |
\D | 匹配非数字, 即不是数字 |
\s | 匹配空白, 即 空格, tab 键, space,换行,回车都属于空白 |
\S | 匹配非空白 |
\w | 匹配单词字符, 即 a-z、 A-Z、 0-9、 _ (汉字) word |
\W | 匹配非单词字符 |
def single_char_match():
"""
匹配单个字符
:return:
"""
ret = re.match(".", "m") # . 匹配任意字符
print(ret.group())
print("-" * 100)
ret = re.match("he.lo", "hello")
print(ret.group())
print("-" * 100)
ret = re.match("[hH]", "Hello") # []匹配所列举的字符
print(ret.group())
print("-" * 100)
ret = re.match("[a-z]", "hello") # []内可以标注一个范围:a-z
print(ret.group())
print("-" * 100)
ret = re.match("[a-z]ello", "hello world")
print(ret.group())
print("-" * 100)
ret = re.match("嫦娥\d号", "嫦娥6号") # \d匹配数字
print(ret.group())
print("-" * 100)
ret = re.match("你\w", "你好啊")
print(ret.group())
if __name__ == '__main__':
single_char_match()
输出结果:
m
----------------------------------------------------------------------------------------------------
hello
----------------------------------------------------------------------------------------------------
H
----------------------------------------------------------------------------------------------------
h
----------------------------------------------------------------------------------------------------
hello
----------------------------------------------------------------------------------------------------
嫦娥6号
----------------------------------------------------------------------------------------------------
你好
三、匹配多个字符
多字符匹配相关的字符必须要用在单字符匹配字符之后
字符 | 功能 |
* | 匹配前一个字符出现 0 次或者无限次, 即可有可无 |
+ | 匹配前一个字符出现 1 次或者无限次, 即至少有 1 次 |
? | 匹配前一个字符出现 1 次或者 0 次, 即要么有 1 次, 要么没有 |
{m} | 匹配前一个字符出现 m 次 |
{m,n} | 匹配前一个字符出现从 m 到 n 次 |
def multi_char_match():
"""
匹配多个字符
:return:
"""
ret = re.match(r"[A-Z][a-z]*", "M")
print(ret.group())
print("-" * 100)
ret = re.match(r"[A-Z][a-z]*", "Aabcd")
print(ret.group())
print("-" * 100)
# 匹配多字符的格式只与前一个单字符格式组合使用,此处*与[a-z]组合使用
ret = re.match(r"[A-Z][a-z]*", "AbbbbAAAA")
print(ret.group())
print("-" * 100)
code_name = ["name1", "_name", "123name", "__name__"]
for name in code_name:
ret = re.match(r"[a-zA-Z_]+\w", name)
if ret:
print(f"{ret.group()} 符合命名规则")
else:
print(f"{name} 不符合命名规则")
print("-" * 100)
ret = re.match(r"[0-9]?[0-9]", "6") # 此时的6匹配的是后面的[0-9]
# ret = re.match(r"\d?\d", "6") # [0-9]可以直接写成\d
print(ret.group())
print("-" * 100)
ret = re.match(r"[1-9]?\d", "09")
print(ret.group())
print("-" * 100)
ret = re.match(r"[a-zA-Z_0-9]{6}", "123abc456def789")
print(ret.group())
print("-" * 100)
# 至少出现6个匹配字符,最多出现20个匹配字符
ret = re.match(r"[a-zA-Z_0-9]{6,20}", "123abc456def&&&&789")
print(ret.group())
print("-" * 100)
if __name__ == '__main__':
multi_char_match()
输出结果:
M
----------------------------------------------------------------------------------------------------
Aabcd
----------------------------------------------------------------------------------------------------
Abbbb
----------------------------------------------------------------------------------------------------
name1 符合命名规则
_name 符合命名规则
123name 不符合命名规则
__name__ 符合命名规则
----------------------------------------------------------------------------------------------------
6
----------------------------------------------------------------------------------------------------
0
----------------------------------------------------------------------------------------------------
123abc
----------------------------------------------------------------------------------------------------
123abc456def
----------------------------------------------------------------------------------------------------
四、匹配开头和结尾
字符 | 功能 |
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
def begin_end_match():
"""
匹配开头和结尾
:return:
"""
# 一般match函数无需设置开头^匹配,但是如果用的是search,则需要用到^
ret = re.search("hello", "nihao hello")
print(ret.group())
print("-" * 100)
ret = re.search("^hello", "nihao hello")
if ret:
print(ret.group())
else:
print("hello不在开头")
print("-" * 100)
web_name = ["http:zhangwei_shi_ge_hun_dan.com", "www.baidu.com", "https://www.bilibili.com/",
"www.http.https.com"]
for name in web_name: # 找到https:开头的网址
ret = re.search(r"^http:[^ ]+", name) # ^ 和 http:连用,[^ ]和+连用-->[^ ]代表非空白
if ret:
print(f"http网址为{ret.group()}")
else:
print(f"{name}不是http网站")
print("-" * 100)
email_name = ["xiaoming@163.com", "88888888@qq.com", "James@163.commmmmmm", "111@1631com"]
for name in email_name:
# \w 和 + 连用, @163\.com和$连用, \.代表转义,因为.在正则表达式中代表任意字符
ret = re.match(r"\w+@163\.com$", name)
if ret:
print(f"符合163格式的邮箱:{ret.group()}")
else:
print(f"不符合163格式的邮箱:{name}")
print("-" * 100)
if __name__ == '__main__':
begin_end_match()
输出结果:
hello
----------------------------------------------------------------------------------------------------
hello不在开头
----------------------------------------------------------------------------------------------------
http网址为http:zhangwei_shi_ge_hun_dan.com
www.baidu.com不是http网站
https://www.bilibili.com/不是http网站
www.http.https.com不是http网站
----------------------------------------------------------------------------------------------------
符合163格式的邮箱:xiaoming@163.com
不符合163格式的邮箱:88888888@qq.com
不符合163格式的邮箱:James@163.commmmmmm
----------------------------------------------------------------------------------------------------
五、匹配分组
字符 | 功能 |
| | 匹配左右任意一个表达式 |
(ab) | 将括号中字符作为一个分组 |
\num | 引用分组 num 匹配到的字符串 |
(?P<name>) | 分组起别名 |
(?P=name) | 引用别名为 name 分组匹配到的字符串 |
def group_match():
"""
匹配分组
:return:
"""
# 匹配0到100
# [1-9]?匹配0个或者1个1-9的字符,\d$代表必须以数字结尾,| 代表满足两边任意一个即可
ret = re.match(r"[1-9]?\d$|100", "99")
print(ret.group())
print("-" * 100)
# 如果\d后没有$,则出现 00,01,02,03...09时,\d会默认匹配到0
# ret = re.match(r"[1-9]?\d", "08")
# print(ret.group())
# print("-" * 100)
email_name = ["xiaoming@163.com", "88888888@qq.com", "James@163.commmmmmm", "111@1631com"]
# 匹配出163邮箱和qq邮箱
for name in email_name:
ret = re.match(r"\w+@(163|qq)\.com$", name) # 加了()代表里面匹配到的内容所属一个分组
if ret:
print(f"符合要求的邮箱:{ret.group()}")
else:
print(f"不符合要求的邮箱:{name}")
print("-" * 100)
dir_path = "D:\pythonProject\project1\current_project.py"
# \在正则表达式用作转义字符,故用 \\ 来代表字符 \
ret = re.match(r"([^\\]+)\\([^\\]+)\\([^\\]+)\\([^\\]+)", dir_path)
print(ret.group())
print(ret.group(1))
print(ret.group(2))
print(ret.group(3))
print(ret.group(4))
print("-" * 100)
# 分组后还可以用 \num代表第几个分组,如\1代表第一个分组
ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", "<html>hh</html>") # \1 匹配的就是 ([a-zA-Z]*)
print(ret.group())
print("-" * 100)
ret = re.match(r"<(\w+)><(\w+)>.+</\2></\1>", "<html><w1>www.baidu.com</w1></html>")
print(ret.group())
print("-" * 100)
# 由于\1 \2等写法易读性较差,所以可以通过(?P<name>)起名字,并通过(?P=name)格式引用
ret = re.match(r"<(?P<name1>\w+)><(?P<name2>\w+)>.+</(?P=name2)></(?P=name1)>",
"<html><w1>www.bilibili.com</w1></html>")
print(ret.group())
if __name__ == '__main__':
group_match()
输出结果:
99
----------------------------------------------------------------------------------------------------
符合要求的邮箱:xiaoming@163.com
符合要求的邮箱:88888888@qq.com
不符合要求的邮箱:James@163.commmmmmm
不符合要求的邮箱:111@1631com
----------------------------------------------------------------------------------------------------
D:\pythonProject\project1\current_project.py
D:
pythonProject
project1
current_project.py
----------------------------------------------------------------------------------------------------
<html>hh</html>
六、re模块中其他函数的使用
1、相关函数的使用
def add(x):
result = x.group()
return str(int(result) + 100)
def other_function():
"""
re模块中的其他函数:search findall sub split
:return:
"""
ret = re.search(r"\d+", "阅读次数:9999,点赞次数:888")
print(ret.group())
print("-" * 100)
ret = re.findall(r"\d+", "阅读次数:9999,点赞次数:888") # 会返回一个list
print(ret)
print("-" * 100)
# sub将匹配到的数据进行进行替换
ret = re.sub(r"\d+", "1000", "int a = 997")
print(ret)
ret = re.sub(r"\d+", lambda x: str(int(x.group()) + 100), "int a = 1200")
print(ret)
ret = re.sub(r"\d+", add, "int a = 1300")
print(ret)
print("-" * 100)
# sub可选择替换的数量
text = "apple apple apple apple"
pattern = r"apple"
replacement = "orange"
new_text = re.sub(pattern, replacement, text, count=3)
print(new_text)
print("-" * 100)
def find_second_match(pattern, text):
matches = re.finditer(pattern, text)
try:
next(matches) # 跳过第一个匹配项
second_match = next(matches) # 获取第二个匹配项
return second_match.group()
except StopIteration:
return None
def use_finditer():
"""
使用finditer
:return:
"""
# 示例用法
text = "abc123def456ghi789"
pattern = r"\d+"
second_match = find_second_match(pattern, text)
print(second_match)
if __name__ == '__main__':
other_function()
print("-----------finditer的使用:-------------")
use_finditer()
print("-----------finditer的使用:-------------")
输出结果:
9999
----------------------------------------------------------------------------------------------------
['9999', '888']
----------------------------------------------------------------------------------------------------
int a = 1000
int a = 1300
int a = 1400
----------------------------------------------------------------------------------------------------
orange orange orange apple
----------------------------------------------------------------------------------------------------
-----------finditer的使用:-------------
456
-----------finditer的使用:-------------
2、迭代器
def number_generator(start=0):
while start <= 5: # 无限循环,持续生成数字
yield start # 程序在这里暂停,start值被return回来,下次函数进来也从这开始
start += 1
return
def use_generator():
"""
使用生成器,理解next
:return:
"""
# # 示例使用
gen = number_generator() # 创建生成器实例,从0开始
print(type(gen))
# print(next(gen)) # 输出 0
# print(next(gen)) # 输出 1
# print(next(gen)) # 输出 2
for i in gen:
print(i)
if __name__ == '__main__':
use_generator()
输出结果:
<class 'generator'>
0
1
2
3
4
5
七、findall函数的一些问题
def use_findall():
"""
findall函数的一些机制问题
:return:
"""
s = 'hello world, now is 2020/7/20 18:48, 现在是2020年7月20日18时48分。'
ret_s = re.sub(r'年|月', r'/', s)
ret_s = re.sub(r'日', r' ', ret_s)
ret_s = re.sub(r'时|分', r':', ret_s)
print(ret_s)
print("-" * 100)
# findall函数有bug,如果pattern中有分组()则执行findall后会返回分组的内容,所以需要在分组中加上?:
# findall 内部的设计机制,在分组前面加?:
pattern = re.compile(r'\d{4}/[01]?[0-9]/[1-3]?[0-9]\s(?:0[0-9]|1[0-9]|2[0-4])\:[0-5][0-9]')
ret = pattern.findall(ret_s)
print(ret)
print("-" * 100)
pattern1 = re.compile(r'\d{4}/[01]?[0-9]/[1-3]?[0-9]\s(0[0-9]|1[0-9]|2[0-4])\:[0-5][0-9]')
# search 没问题
ret1 = pattern1.search(ret_s)
print(ret1.group())
if __name__ == '__main__':
use_findall()
输出结果:
hello world, now is 2020/7/20 18:48, 现在是2020/7/20 18:48:。
----------------------------------------------------------------------------------------------------
['2020/7/20 18:48', '2020/7/20 18:48']
----------------------------------------------------------------------------------------------------
2020/7/20 18:48
八、re模块中的split函数
# re模块的split函数可以根据多个字符进行切割
def use_split():
# 根据: | 空格对后续字符串进行切割
ret = re.split(r":| ", "info:xiaoZhang 33 shandong")
print(ret)
if __name__ == '__main__':
use_split()
输出结果:
['info', 'xiaoZhang', '33', 'shandong']
九、正则表达式的贪婪与非贪婪
def greedy_and_no_greedy():
"""
python的正则表达式默认是贪婪的,会包含尽可能多的字符串,通过加?可以变为非贪婪
:return:
"""
s = "This is a number 234-235-22-423"
# .+ 会一直读取到字符3,因为有\d所以4不能被.+读完
ret = re.match(r".+(\d+-\d+-\d+-\d+)", s)
print(ret.group(1))
print("-" * 100)
# 加了?后变为非贪婪
ret = re.match(r".+?(\d+-\d+-\d+-\d+)", s)
print(ret.group(1))
print("-" * 100)
print(re.match(r"aa(\d+)", "aa2343ddd").group(1))
print(re.match(r"aa(\d+?)", "aa2343ddd").group(1))
print(re.match(r"aa(\d+)ddd", "aa2343ddd").group(1))
# 字符要匹配ddd,所以\d+?就算是非贪婪也必须读完2343
print(re.match(r"aa(\d+?)ddd", "aa2343ddd").group(1))
if __name__ == '__main__':
greedy_and_no_greedy()
输出结果:
4-235-22-423
----------------------------------------------------------------------------------------------------
234-235-22-423
----------------------------------------------------------------------------------------------------
2343
2
2343
2343
十、函数的一些参数
# re.A 不让\w 匹配汉字
# re.I 是否区分大小写
# re.S 可以让.匹配上\n
def use_option():
print(re.match(r'\w*', 'abc函', flags=re.A).group())
print("-" * 100)
print(re.match(r'a*', 'aA', flags=re.I).group())
print("-" * 100)
print(re.match(r'.*', 'abc\ndef', flags=re.S).group())
if __name__ == '__main__':
use_option()
输出结果:
abc
----------------------------------------------------------------------------------------------------
aA
----------------------------------------------------------------------------------------------------
abc
def