正则表达式-python

写脚本代码的时候,需要正则表达式的使用

这里对正则表达式做一个详细的梳理

菜鸟教程

特殊字符类

操作符 说明 实例
. 表示的那个字符
[ ] 字符集,对单个字符给出取值范围 [abc]表示a,b,c[a-z]表示a-z单个字符,[0-9]表示数字字符
非字符集,对单个字符给出排除范围 abc表示非a或b或c的单个字符
* 前一个字符0次或无限次扩展 abc+表示ab,abc,abcc,abccc…
+ 前一个字符1次或无限次扩展 abc+表示abc,abcc,abccc…
前一个0次或1次扩展 abc?表示ab,abc
\ 左右表达式任意一个 abc\ def表示abc,def
{m} 扩展前一个字符m次 ab{2}c表示abbc
{m,n} 扩展前一个字符m至n次(含n) ab{1,2}c表示abc,abbc
^ 匹配字符串开头 ^abc表示abc且在一个字符串的开头
$ 匹配字 符串结尾 abc$表示abc且在一个字符串的结尾
() 分组标记,内部只能使用\ 操作符 (abc)表示abc,(abc\ def)表示(abc,def)
\d 数字,等价于[0-9]
\D 小写\d的非
\w 单词字符,等价于[A-Z,a-z,0-9,_]
\W 小写w的非
\s 空白符
\S 小写s的非

修饰符-可选标志

修饰符 描述
re.L 做本地化识别匹配
re.I 使匹配对大小写不敏感
re.M 多行匹配,影响^和$
re.S 匹配包括换行符在内的所有字符
re.U 根据Unicode字符集解析字符,这个标志影响\w,\W,\b,\B
re.X 该标志通过给你更灵活的格式以便你将正则表达式写的更易于理解

边界字符

字符 功能
^ 匹配字符串开头
$ 匹配字符串结尾
\b 匹配单词的边界
\B 匹配非单词的边界
  1. 匹配qq邮箱:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    qq = "8625005@qq.com"
    qq = "8625005@qq.com.cn"
    qq = "8625005@qq.com.126.com"
    pattern = r"[1-9]\d{4,9}@qq.com"
    o = re.match()
    # 对于三个qq定义都能够得到相同的结果,匹配失去意义
    pattern = r"[1-9]\d{4,9}@qq.com$"
    o = re.match()
    # 必须以@qq.com为结尾
  2. 匹配单词边界:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    pattern = r".*\bab"
    # 单词以ab为左边界
    s = "12345 abc"
    o = re.match(pattern.s)# 结果为12345 ab
    pattern = r".*ab\b"
    # 单词以ab为右边界
    s = "12345 abc"
    o = re.match(pattern.s)# 结果为None
    # 将s = “12345 cab”,结果为12345 cab
  3. 匹配非单词边界:
    将上面的小b换成B,输出刚好反过来

    就是不以ab作为边界才行,以ab作为边界的字符串范围匹配失败

转义字符

s = “\\t123”,因为转义字符的存在,print结果为\t123

o = re.match("\\\\t\d*",s)

即每一个反斜杠都需要转义才能正确输出,解决方法:加“r”前缀

常用方法

  1. re.match()匹配

    尝试从 字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回None,语法格式如下:re.match(pattarn,string,flags = 0)匹配成功返回一个对象eg:o = re.match(pattern,s)

    • 可用接口:

      o.group():返回匹配的字符串

      o.span():返回匹配的字符串的范围eg:(0,5)就代表有5个字符相同

      o.start():开始位置,肯定是0

  2. re.search()

    同样有group(),span(),start()接口同match

    区别只在于match必须从头开始匹配,search是检索整个字符串

  3. re.sub/subn()

    搜索和替换功能。这两个函数的功能几乎完全相同,将某个字符串中所有匹配正则表达式的部分替换成其他字符串。sub函数返回一个替换后的结果,subn函数返回一个替换后的元组,元组的第一个元素是替换后的结果,第二个元素是替换的总数。

    语法规则:

    1
    2
    3
    re.sub(pattern,repl,string,coutn = 0,flags = 0)
    eg:
    re.sub("\s","",string) #将string中的空白符替换为空字符
  4. re.compile()

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

    1
    2
    3
    4
    5
    re.compile(pattern[,flags])
    eg:
    s = re.compile("[0-9]?\d")
    o = s.match("99")
    就等价于o = re.match("[0-9]?\d","99")
  5. re.split

    split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

    1
    2
    3
    4
    5
    re.split(pattern, string[, maxsplit=0, flags=0])
    eg:
    s = "a11b22c33"
    re.split(r"\d+",s)#结果为:[“a”,“b”,“c”,“”]
    maxsplit指定分割次数
  6. findall()和re.finditer()

    在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

    注意: match 和 search 是匹配一次 findall 匹配所有。

    1
    2
    3
    4
    5
    findall(string[, pos[, endpos]])
    eg:
    pattern = re.compile(r"\d+")
    result1 = pattern.findall("abc 123 def 456")
    #result1结果为:[123,456]

    finditer和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

    1
    re.finditer(pattern, string, flags=0)

    通过遍历输出的迭代器可以得到匹配内容的对象,再调用group()方法就可以得到匹配内容

匹配多个字符串

  1. |:表示逻辑或的意思

    eg:匹配0-100的数字:
    pattern = r”[1-9]?\d$ | 100$”

    为什么要加结尾匹配符

    因为两个选择有重叠的部分,假设不加结尾符,当s = 100的时候

    o = re.search(pattern,s)

    o.group()的结果为10,

  2. []:方括号内的元素择一匹配

    [xyz]和x|y|z的意思相同

    [ab][cd]和ab|cd的意思就不同了

分组

():括号内的内容作为一个分组

字符 功能
(ab) 将括号中的字符作为一个分组
\num 引用分组num匹配到的字符串
(?p<name>) num多的话容易乱,用这个东西起名字
(?p=name) 用名字来进行引用
1
2
3
4
5
6
7
# 匹配电话号
pattern = r"(\d{3,4})-([1-9]\d{4,7}$)"
s = "010-786545"
o = re.match(pattern,s)
print(o.groups()) #结果输出一个元组("010","786545")
print(o.group(1)) #结果:010
print(o.group(2)) #结果:786545
1
2
3
4
5
6
7
8
9
# \num的使用,匹配网页标签内的数据
pattern = r"<.+><.+>.+<.+><.+>"
s = "<html><head>head部分</head></html>"
o = re.match(pettern,s)
# 将pattern进行精确化
pattern = r"<(.+)><(.+)>.+</\1></\2>"
# 后面两个\1,\2分别对应前面两个分组
# 这时候分组内容可以用别名代替
pattern = r"<(?<k_html>.+)><(?<k_head>.+)>.+</?<k_html>></?<k_head>"