首页 > 技术文章 > Python - 正则表达式

fade-color 2021-05-02 14:46 原文

1. match方法

re.match尝试从字符串起始位置匹配一个模式,如果不是起始位置匹配成功的话,match就返回None

。语法格式如下:

  • re.match(pattern, string, flags=0)

    • pattern:匹配的正则表达式
    • string:要匹配的字符串
    • flags:标志位,用于控制正则表达式的匹配方式
  • 标志位:

    修饰符 描述
    re.I 忽略大小写
    re.L 做本地化(locale-aware)匹配
    re.M 多行匹配,影响 ^$
    re.S 使 . 匹配包括换行符在内的所有字符
    re.U 根据Unicode字符集解析字符。这个标志影响 \w\W\b\B
    re.X 该标志通过给予你更灵活的方式以便你将表达式写的更易于理解

match方法的使用

import re

s = "hello world"
pattern = "hello"
rs = re.match(pattern, s)

print(rs)
# <re.Match object; span=(0, 5), match='hello'>

print(dir(rs))  # 查看rs的方法
# ['__class__', '__copy__', ..., 'pos', 're', 'regs', 'span', 'start', 'string']

print(rs.group())  # 返回s中匹配到的字符串
# hello

print(rs.span())  # 返回s中匹配到的范围
# (0, 5)
print(rs.start())  # 返回s中匹配到的字符串起始位置
# 0

2. 常用匹配符

符号 描述
. 匹配除换行符\n以外任意一个字符
[] 匹配列表中的字符
\w 匹配字母、数字、下划线,即 a-z,A-Z,0-9,_
\W 匹配不是字母、数字、下划线的字符
\s 匹配空白字符,即空格(\n\t
\S 匹配不是空白的字符
\d 匹配数字,即 0-9
\D 匹配非数字的字符
s_list = ["1", "6", "D", "\t", "a", "\n", "_", "."]

# --------------- "."的使用 --------------- #
print([re.match(".", s) is not None for s in s_list])  # 除\n以外任意字符
# [True, True, True, True, True, False, True, True, True, True, True]

# --------------- "[]"的使用 --------------- #
print([re.match("[0-9a-z]", s) is not None for s in s_list])  # 数字和小写字母
# [True, True, False, False, True, False, False, False, False, False, False]

# --------------- "\w"的使用 --------------- #
print([re.match("\w", s) is not None for s in s_list])  # a-z A-Z 0-9 _
# [True, True, True, False, True, False, True, False, False, False, False]

# --------------- "\W"的使用 --------------- #
print([re.match("\W", s) is not None for s in s_list])  # 除a-z A-Z 0-9 _以外的字符
# [False, False, False, True, False, True, False, True, True, True, True]

# --------------- "\s"的使用 --------------- #
print([re.match("\s", s) is not None for s in s_list])  # 空白字符\t \n等
# [False, False, False, True, False, True, False, False, False, False, False]

# --------------- "\d"的使用 --------------- #
print([re.match("\d", s) is not None for s in s_list])  # 数字
# [True, True, False, False, False, False, False, False, False, False, False]

3. 限定符

符号 描述 符号 描述
* 匹配0次或多次 {m} 重复m次
+ 匹配一次或多次 {m,n} 重复m到n次
? 匹配一次或0次 {m,} 至少m次
s_list = ["123qwe", "qwerty", "1qwe", "12345"]

# --------------- "*"的使用 --------------- #
print([re.match("\d*", s) is not None for s in s_list])  # 匹配0个或多个数字
# [True, True, True, True]

# --------------- "+"的使用 --------------- #
print([re.match("\d+", s) is not None for s in s_list])  # 匹配一个或0个数字
# [True, False, True, True]

# --------------- "?"的使用 --------------- #
print([re.match("\d?", s) is not None for s in s_list])  # 匹配一个或0个数字
# [True, True, True, True]

# --------------- "{m}"的使用 --------------- #
print([re.match("\d{3}", s) is not None for s in s_list])  # 匹配3个数字
# [True, False, False, True]

# --------------- "{m,n}"的使用 --------------- #
print([re.match("\d{2,5}", s) is not None for s in s_list])  # 匹配2到3个数字
# [True, False, False, True]

# --------------- "{m,}"的使用 --------------- #
print([re.match("\d{3,}", s) is not None for s in s_list])  # 至少3个数字
# [True, False, False, True]

4. 边界字符

字符 功能
^ 匹配开头
$ 匹配结尾
\b 匹配单词边界
\B 匹配非单词边界
[^] 匹配除列表中指定字符以外的所有字符
# --------------- "$"用法,匹配QQ邮箱 --------------- #
# 5-10位数字,@qq.com结尾
pattern = r"[1-9]\d{4,9}@qq.com$"
match_list = ["318821221@qq.com", "a31234@qq.com", "123.231@qq.com", "3123213@163.com", "3127721@qq.com.cn"]
print([bool(re.match(pattern, s)) for s in match_list])
# [True, False, False, False, False]

# --------------- "^"匹配开头 --------------- #
pattern = r"^hello.*"
match_list = ["hello python", "hi python"]
print([bool(re.match(pattern, s)) for s in match_list])
# [True, False]

# --------------- "\b"匹配单词左边界 --------------- #
pattern = r".*\bab"
match_list = ["12345 abc", "baby", "absolute", "stab"]
print([bool(re.match(pattern, s)) for s in match_list])
# [True, False, True, False]

# --------------- "\b"匹配单词右边界 --------------- #
pattern = r".*ab\b"
match_list = ["12345 abc", "baby", "absolute", "stab"]
print([bool(re.match(pattern, s)) for s in match_list])
# [False, False, False, True]

# --------------- "\B"匹配非单词边界 --------------- #
pattern = r".*\Bab"  # 非ab开头
match_list = ["12345 abc", "baby", "absolute", "stab"]
print([bool(re.match(pattern, s)) for s in match_list])
# [False, True, False, True]

5. search方法

searchmactch的区别:

  • re.match()只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None
  • re.search()匹配整个字符串,直到找到一个匹配。
pattern = r"Love"
s = "I Love You"

print(re.match(pattern, s))
# None
print(re.search(pattern, s))
# <re.Match object; span=(2, 6), match='Love'>

6. 匹配多个字符串

search()方法搜索一个字符串,想要搜索多个字符串,使用择一匹配符号 | 。择一匹配符号和逻辑或类似,只要满足任何一个,就算匹配成功。

pattern = r"aa|bb|cc"
s = "my name is cc"

print(re.search(pattern, s))
# <re.Match object; span=(11, 13), match='cc'>

# --------------- 匹配0-100之间的所有数字 --------------- #
pattern = r"[1-9]?\d$|100$"
s_list = ["1", "0", "63", "121", "100", "9218", "010"]
print([bool(re.match(pattern, s)) for s in s_list])
# [True, True, True, False, True, False, False]

对于单个字符使用或关系时,使用字符集 [] 和择一匹配符 | 的效果是相同的。

pattern = r"[ab][cd]"
s_list = ["ab", "ac", "bd", "cd", "ad"]
print([bool(re.match(pattern, s)) for s in s_list])
# [False, True, True, False, True]

# 等同于
pattern = r"ac|ad|bc|bd"
print([bool(re.match(pattern, s)) for s in s_list])
# [False, True, True, False, True]

7. 分组

我们可以用小括号()来进行分组,括起来的部分会成为一组,通过group()方法的参数获取指定的组匹配的字符串。

字符 功能
(ab) 对括号内的字符进行分组
\num 引用分组num匹配到的字符串
(?P<name>) 分别起组名
(?P=name) 引用别名为name分组匹配到的字符串

8. sub和subn搜索与替换

subsubn用于实现搜索和替换功能。这两个函数的功能几乎完全相同,都是将字符串所匹配正则表达式的部分替换成其他字符串。用于替换的部分可以使一个字符串,也可以是一个返回字符串的函数。

sub函数返回替换后的结果;subn函数返回一个由替换后的字符串替换的总数组成的元组。

  • re.sub(pattern, repl, string, count=0, flags=0)
    • pattern:匹配的正则表达式
    • repl:替换的字符串,也可以是一个返回字符串的函数
    • string:被替换的原始字符串
    • count:模式匹配后替换的最大次数,默认0表示替换所有的匹配
    • flags:标志位,用于控制正则表达式的匹配方式
phone = "2004-959-559  # 这是一个国外电话号码"
# --------------- 删除字符串中的注释 --------------- #
num = re.sub(r"#.*$", "", phone)
# 2004-959-559 

# --------------- 删除除电话号码以外的所有字符 --------------- #
num = re.sub(r"\D", "", phone)
# 2004959559

# --------------- subn删除除电话号码以外的所有字符 --------------- #
result = re.subn(r"\D", "", phone)
# ('2004959559', 16)

9. compile方法

compile()方法用于编译正则表达式,生成一个正则表达式(Pattern)对象,供match()search()这两个函数使用。语法格式为:

  • re.compile(pattern[, flags])
    • pattern:一个字符串形式的正则表达式
    • flags:可选,标志位,用于控制正则表达式的匹配方式
# --------------- compile的使用 --------------- #
s = "first123 line"
regex = re.compile(r"\w+")
print(regex.match(s))

10. findall方法和finditer方法

  • findall()方法在字符串中找到正则表达式所匹配的所有字符串,并返回一个列表,如果没找到匹配子串则返回空列表。语法格式如下:

    • findall(pattern, string, flags=0)
      • pattern:匹配的正则表达式
      • string:要匹配的字符串
    # --------------- findall的使用 --------------- #
    s = "first 1 second 2 third 3"
    rs = re.findall(r"\w+", s)
    print(rs)
    # ['first', '1', 'second', '2', 'third', '3']
    
  • finditer()方法与findall类似,只不过finditer()返回的是一个迭代器对象,获取匹配到的字符串时需要遍历并调用item.group()方法。

    # --------------- finditer的使用 --------------- #
    s = "first 1 second 2 third 3"
    iterator = re.finditer(r"\w+", s)
    print(iterator)
    # <callable_iterator object at 0x7fd7129696d0>
    for item in iterator:
        print(item.group(), end="\t")
    # first	1	second	2	third	3	
    

11. split方法

split()方法用于根据正则表达式分割字符串,它返回一个分割后的子串列表。

  • re.split(pattern, string[, maxsplit=0, flags=0])
    • pattern:要匹配的表达式
    • string:要匹配的字符串
    • maxsplit:最大分割次数,默认为0,即不限制
# --------------- split的使用 --------------- #
s = "first 1 second 2 third 3"
# 按数字分割
print(re.split(r"\d+", s))
# ['first ', ' second ', ' third ', '']

# 指定maxsplit=1
print(re.split(r"\d+", s, maxsplit=1))
# ['first ', ' second 2 third 3']

12. 贪婪模式与非贪婪模式

在Python中正则匹配默认是贪婪的,总是尝试匹配尽可能多的字符。非贪婪模式则是尽可能少的匹配字符可以使用*?+{m,n}后面加 ? 使得贪婪匹配变为非贪婪匹配。

  • 例1:

    # --------------- 贪婪模式 --------------- #
    rs = re.match(r"(.+)(\d+-\d+-\d+)", "This is my tel: 133-1234-1234")
    print(rs.group(1))
    # This is my tel: 13
    print(rs.group(2))
    # 3-1234-1234
    
    # --------------- 非贪婪模式 --------------- #
    rs = re.match(r"(.+?)(\d+-\d+-\d+)", "This is my tel: 133-1234-1234")
    print(rs.group(1))
    # This is my tel: 
    print(rs.group(2))
    # 133-1234-1234
    
  • 例2:

    # --------------- 贪婪模式 --------------- #
    rs = re.match(r"abc(\d+)", "abc123")
    print(rs.group(1))  # 123
    
    # --------------- 非贪婪模式 --------------- #
    rs = re.match(r"abc(\d+?)", "abc123")
    print(rs.group(1))  # 1
    

推荐阅读