python正则表达式学习记录

一、正则表达式需要用到的模块和函数

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值