语法

常用匹配规则

通过py中的re模块来学习并使用正式表达式

  1. import re

匹配字符

符号 说明
. 匹配任意一个字符,除了换行符\n
[abc] 匹配abc中的任意一个字符
\d 匹配一个数字,即0-9
\D 匹配非数字,即不是数字
\s 匹配空白,即空格,tab键
\S 匹配非空白,除空格,tab键之类的
\w 匹配单词字符,即a-z、A-Z、_(字母数字下划线)
\W 匹配非单词字符

匹配字符数量

符号 说明
* 匹配前一个字符出现0次或无限次,即可有可无
+ 出现1次或者无限次,即至少有1次
\? 出现1次或者0次,即要么1次,要么没有
{m} 出现m次
{m,} 至少出现m次
{n,m} 出现从n到m次

分组匹配

符号 说明
| 匹配左右任意一个表达式
(ab) 讲括号中字符作为一个分组
\num 引用分组num匹配到的字符串
(?P) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串

re库

re.complie

re.compile()是用来优化正则的,它将正则表达式转化为对象。re.search(pattern, string)的调用方式就转换为 pattern.search(string)的调用方式,多次调用一个正则表达式就重复利用这个正则对象,可以实现更有效率的匹配

语法格式

  1. re.compile(pattern, flags=0)
  • pttern 匹配模式。即要表达的正则表达式

从compile()函数的定义中,可以看出返回的是一个匹配对象,它单独使用就没有任何意义,需要和findall(), search(), match()搭配使用。

实践操作

常规的re.findall的写法是这样写的,但是我们可以结合compile()函数来使用

  1. import re
  2. obj=re.findall(r'1\d{10}','我的手机号码是:152352100000')
  3. print(obj)

输出的结果为:[‘15235210000’]

与compile()函数结合:

  1. import re
  2. patter=re.compile(r'1\d{10}')
  3. obj=patter.findall('我的手机号码是:1523521000077')
  4. print(obj)

输出的结果为:[‘15235210000’]

re.findall

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

语法格式

  1. re.findall(pattern, string, flags=0)
  2. pattern.findall(string[, pos[, endpos]])
  • pattern 匹配模式。
  • string 待匹配的字符串。
  • pos 可选参数,指定字符串的起始位置,默认为 0。
  • endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。

    实践操作

    1. import re #导入re模块
    2. lst=re.findall(r'\d+','我的电话是:10086,她的电话是:10011')#检索字符串中所有的数字
    3. print(lst)
    输出结果为:[‘10086’, ‘10011’]
    1. import re
    2. lst1=re.findall(r'\d+','ysegsde2345dgtesget09098')
    3. print(lst1)
    输出结果为:[‘2345’, ‘09098’]

re.finditer

语法格式

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

  1. re.finditer(pattern, string, flags=0)
  • pattern 匹配模式。
  • string 待匹配的字符串。

    实践操作

    1. import re
    2. item=re.finditer(r'\d+','我的电话是:10086,她的电话是:10011')
    3. for i in item:
    4. print(i.group()) #要通过group来取数据

    输出结果为:
    10086
    10011

    re.sub

    检查和替换

    语法格式

    1. re.sub(pattern, repl, string, count=0, flags=0)
  • pattern : 正则中的模式字符串。

  • repl : 替换的字符串,也可为一个函数。
  • string : 要被查找替换的原始字符串。
  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
  • flags : 编译时用的匹配模式,数字形式。

    1. 1).re.I(re.IGNORECASE): 忽略大小写
    2. 2).re.M(MULTILINE): 多行模式,改变'^'和'$'的行为
    3. 3).re.S(DOTALL): 点任意匹配模式,改变'.'的行为
    4. 4).re.L(LOCALE): 使预定字符类 \w \W \b \B \s \S 取决于当前区域设定
    5. 5).re.U(UNICODE): 使预定字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性
    6. 6).re.X(VERBOSE): 详细模式。这个模式下正则表达式可以是多行,忽略空白字符,并可以加入注释

    前三个为必选参数,后两个为可选参数。

    实践操作

    1. #re.sub 实现目标的搜索和查找 2021-12-13
    2. data='Pyhton是很受欢迎的编程语言'
    3. res=re.sub(r'[a-zA-Z]+','C#',data) #字符集的范围+号代表字符模式出现1次以上
    4. print(res)

    输出结果为:C#是很受欢迎的编程语言

    1. # 将里面的分数都替换成100分
    2. msg='语文=99,数学=78,英语=90'
    3. m=re.sub(r'\d+','100',msg)
    4. print(m)

    输出结果为:语文=100,数学=100,英语=100

    1. import re
    2. data='save your time'
    3. res=re.sub('s','S',data) #讲小s替换成大写的S
    4. print(res)

    输出结果为:Save your time

    re.macth

    尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
    匹配成功re.match方法返回一个匹配的对象,否则返回None。可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式

    语法格式

    1. re.match(pattern, string, flags=0)
  • pattern 匹配模式。

  • string 待匹配的字符串。

    实践操作

    在起始位置匹配
    1. import re
    2. s=re.match(r'\d+','12353442wwww上的人人dddd234g') #从头开始,是否符合是数字要求,如果是,返回数字,如果不是,返回none
    3. print(s)
    输出结果为:
    1. <_sre.SRE_Match object; span=(0, 8), match='12353442'> #表示有匹配对象
    如果要正常的输出,加上一个.group()
    1. import re
    2. s=re.match(r'\d+','12353442wwww上的人人dddd234g') #从头开始,是否符合是数字要求,如果是,返回数字,如果不是,返回none
    3. print(s.group())
    输出结果为:12353442

在起始位置不匹配

  1. import re
  2. s=re.match(r'\d+','wwww上的人人dddd234g') #从头开始,是否符合是数字要求,如果是,返回数字,如果不是,返回none
  3. print(s)

输出结果为:None

re.search

扫描整个字符串并返回第一个成功的匹配。从任何一个地方开始匹配,只匹配一次。
注意:是一次匹配,如果后面还有匹配的也不会查找了。使用group()来获取数据

语法格式

  1. re.search(pattern, string, flags=0)
  • pattern 匹配模式。
  • string 待匹配的字符串。

    实践操作

    1. import re
    2. r=re.search('abc','helabcloabc')
    3. print(r)
    输出结果为:
    1. <_sre.SRE_Match object; span=(3, 6), match='abc'> #表示有匹配对象
    如果要正常的输出,加上一个.group()
    1. import re
    2. r=re.search('abc','helabcloabc')
    3. print(r.group())
    输出结果为:abc
    1. #2022-01-21 search,找到一个结果就返回,返回的结果是match对象,拿到数据需要.group()
    2. import re
    3. item=re.search(r'\d+','我的电话是:10086,她的电话是:10011')
    4. print(item.group())
    输出结果为:10086

Match对象有几个常用的方法:
group(): 用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group()group(0)
span(): 返回匹配字符串的起始位置
start():用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
end():用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0

  1. import re
  2. r=re.search('abc','helabcloabc')
  3. if r:
  4. print(r.group())
  5. print(r.span())
  6. print(r.start())
  7. print(r.end())

输出结果为:
image.png

  1. import re
  2. match=re.search(r'([a-z]+) ([a-z]+)','hello Kitty hellobaby hello world')# 注意此时是区分大小写的
  3. if match:
  4. print(match.group(0))
  5. print(match.group(1))#获取第一个分组的字符串
  6. print(match.group(2))#获取第二个分组的字符串
  7. print(match.groups())

输出结果为:
image.png
上面的正则表达式表示两组有多个a-z之间的任意字符组成的多个字符串,并且两组之间是有空格的。其中match.groups()表示的意思是(m.group(1), m.group(2), …)search只要找到符合要求的字符串则不会继续查找,但是事实上后面仍然符合正则的仍然是存在的。比如:hello world
要想所有的都获取到,考虑使用findall()

贪婪模式非贪婪模式

.* 贪婪模式

  • 在满足条件的情况下,尽可能多的去匹配到数据

    .*? 非贪婪模式

  • 在满足条件的情况下,尽可能少的去匹配(写爬虫用的比较多)