re模块操作

  • 使用过程

image.png

  • match方法
    • 作用:从字符串的起始位置匹配正则表达式,如果没有找到返回None
    • 语法格式:re.match(pattern, string, flags=0)
      • pattern:匹配的正则表达式
      • string:待匹配的字符串
      • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等
    • 可以使用group(num) 或 groups()来获取所匹配的字符串
      • group(num=0):默认返回所匹配的整个表达式的字符串,也可以指定num的值从而返回对应的小组字符串
      • groups():返回一个包含所有小组字符串的元组,从1到最大的小组号
  • 示例

image.png
说明:re.match()能够匹配出以xxx开头的字符串

匹配单个字符

image.png

  1. import re
  2. ret = re.match(".", "M")
  3. print(ret.group()) # M
  4. ret = re.match("t.o", "too")
  5. print(ret.group()) # too
  6. ret = re.match("t.o", "two")
  7. print(ret.group()) # two
  1. import re
  2. # 匹配大小写字母
  3. ret = re.match("[h]", "hello Python")
  4. print(ret.group()) # h
  5. ret = re.match("[H]", "Hello Python")
  6. print(ret.group()) # H
  7. ret = re.match("[hH]", "hello Python")
  8. print(ret.group()) # h
  9. ret = re.match("[hH]", "Hello Python")
  10. print(ret.group()) # H
  11. ret = re.match("[hH]ello Python", "Hello Python")
  12. print(ret.group()) # Hello Python
  13. # 匹配0到9的第一种写法
  14. ret = re.match("[0123456789]Hello Python", "7Hello Python")
  15. print(ret.group()) # 7Hello Python
  16. # 匹配0到9的第二种写法
  17. ret = re.match("[0-9]Hello Python", "7Hello Python")
  18. print(ret.group()) # 7Hello Python
  19. ret = re.match("[0-35-9]Hello Python", "7Hello Python")
  20. print(ret.group()) # 7Hello Python
  21. # 下面这个正则表达式不能够匹配到数字4,因此ret为None
  22. ret = re.match("[0-35-9]Hello Python", "4Hello Python")
  23. print(ret.group()) if ret else print("None") # None
  1. import re
  2. ret = re.match("嫦娥\d号", "嫦娥1号发射成功")
  3. print(ret.group()) # 嫦娥1号
  4. ret = re.match("嫦娥\d号", "嫦娥2号发射成功")
  5. print(ret.group()) # 嫦娥2号
  6. ret = re.match("嫦娥\d号", "嫦娥3号发射成功")
  7. print(ret.group()) # 嫦娥3号

匹配多个字符

image.png

  1. import re
  2. # 要求:字符串的第一个字母是大写字母,后面都是小写字母并且数量是任意多个
  3. ret = re.match("[A-Z][a-z]*", "MM")
  4. print(ret.group()) # M
  5. ret = re.match("[A-Z][a-z]*", "MnnM")
  6. print(ret.group()) # Mnn
  7. ret = re.match("[A-Z][a-z]*", "Aabcdef")
  8. print(ret.group()) # Aabcdef
  1. import re
  2. names = ["name1", "_name", "2_name", "__name__"]
  3. for name in names:
  4. # 判断变量名是否有效
  5. ret = re.match("[a-zA-Z_]+[\w]*", name)
  6. if ret:
  7. print("%s符合要求" % ret.group()) # 0 1 3
  8. else:
  9. print("%s不符合要求" % name) # 2
  1. import re
  2. ret = re.match("[1-9]?[0-9]", "7")
  3. print(ret.group()) # 7
  4. ret = re.match("[1-9]?\d", "33")
  5. print(ret.group()) # 33
  6. ret = re.match("[1-9]?\d", "09")
  7. print(ret.group()) # 0
  1. import re
  2. ret = re.match("[a-zA-Z0-9_]{6}", "12a3g45678")
  3. print(ret.group()) # 12a3g4
  4. ret = re.match("[a-zA-Z0-9_]{8,20}", "1ad12f23s34455ff66")
  5. print(ret.group()) # 1ad12f23s34455ff66
  6. ret = re.match('[a-zA-Z0-9_]{4,20}@163.com', "luke1@163.com")
  7. print(ret.group()) # luke1@163.com

匹配开头结尾

image.png

  1. import re
  2. # 判断是否是合法的163邮箱
  3. email_list = ["xiaoWang@163.com", "xiaoWang@163.comheihei", ".com.xiaowang@qq.com"]
  4. for email in email_list:
  5. ret = re.match("[\w]{4,20}@163\.com$", email)
  6. if ret:
  7. print("%s符合要求" % ret.group()) # 0
  8. else:
  9. print("%s不符合要求" % email) # 1 2
  10. # 判断是否不是以4、7结尾的11位手机号码
  11. tel_list = ["13100001234", "18912344321", "10086", "18800007777"]
  12. for tel in tel_list:
  13. ret = re.match("1\d{9}[0-35-68-9]$", tel)
  14. if ret:
  15. print("%s符合要求" % ret.group()) # 1
  16. else:
  17. print("%s不符合要求" % tel) # 0 2 3

匹配分组

image.png
[^abc] —> 匹配除了a、b、c之外的字符
[^0-9] —> 匹配除了数字之外的字符

  1. # 需求:匹配出0-100之间的数字
  2. import re
  3. list1 = ['0', '00', '08', '88', '100', '101']
  4. for item in list1:
  5. ret = re.match('[1-9]?\d$|100', item)
  6. if ret:
  7. print('{}在0-100之间'.format(ret.group())) # 0 88 100
  8. else:
  9. print('{}不在0-100之间'.format(item)) # 00 08 101
  1. # 需求:匹配出163、126、qq邮箱
  2. import re
  3. email_list = ["xiaoWang@163.com", "xiaoWang@qq.com", "xiaoWang@126.com",
  4. "xiaoWang@163.comheihei", ".com.xiaowang@qq.com"]
  5. for email in email_list:
  6. ret = re.match('\w{4,20}@(163|126|qq)\.com$', email)
  7. if ret:
  8. print('{}符合要求'.format(ret.group())) # 0 1 2
  9. else:
  10. print('{}不符合要求'.format(email)) # 3 4
  1. import re
  2. # 提取区号和电话号码
  3. ret = re.match('(\d+)-(\d+)', '010-66668888')
  4. if ret:
  5. print(ret.group()) # 010-66668888
  6. print(ret.group(1)) # 010
  7. print(ret.group(2)) # 66668888
  8. # ([^-]+)代表没有遇到小横杠-就一直匹配下去
  9. ret = re.match('([^-]+)-(\d+)', '我很帅abc123-66668888')
  10. if ret:
  11. print(ret.group()) # 我很帅abc123-66668888
  12. print(ret.group(1)) # 我很帅abc123
  13. print(ret.group(2)) # 66668888
import re

# 单个引用分组
ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>", "<html>hh</html>")
print(ret.group()) if ret else print('None')  # <html>hh</html>

ret = re.match("<[a-zA-Z]*>\w*</[a-zA-Z]*>", "<html>hh</htmlbalabala>")
print(ret.group()) if ret else print('None')  # <html>hh</htmlbalabala>

ret = re.match(r"<([a-zA-Z]*)>\w*</\1>", "<html>hh</html>")
print(ret.group()) if ret else print('None')  # <html>hh</html>

ret = re.match("<[a-zA-Z]*>\w*</\1>", "<html>hh</htmlbalabala>")
print(ret.group()) if ret else print('None')  # None

# 多个引用分组
labels = ["<html><h1>www.cskaoyan.com</h1></html>",
          "<html><h1>www.cskaoyan.com</h2></html>"]

for label in labels:
    ret = re.match(r'<([a-z]+)><(\w*)>.*</\2></\1>', label)
    if ret:
        print("%s符合要求" % ret.group())  # 0 
    else:
        print("%s不符合要求" % label)  # 1
import re

# 给分组起别名,通过别名来引用分组
label1 = '<html><h1>www.cskaoyan.com</h1></html>'
label2 = '<html><h1>www.cskaoyan.com</h2></html>'

ret = re.match(r'<(?P<n1>\w*)><(?P<n2>\w*).*</(?P=n2)></(?P=n1)>', label1)
print(ret.group()) if ret else print('None')  # '<html><h1>www.cskaoyan.com</h1></html>'

ret = re.match(r'<(?P<name1>\w*)><(?P<name2>\w*)>.*</(?P=name2)></(?P=name1)>', label2)
print(ret.group()) if ret else print('None')  # None

# 注意:(?P<name>)和(?P=name)中的字母P需要大写

re模块的高级用法

search方法

  • 作用:扫描整个字符串并返回第一个成功的匹配
  • 语法格式:re.search(pattern, string, flags=0)
  • match和search的区别:match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,返回None;而search匹配整个字符串,直到找到一个匹配 ```python import re

ret = re.search(r”\d+”, “阅读次数为9999”) print(type(ret)) # print(ret.group()) # 9999

ret = re.search(r’(.) are (.?) .*’, “Cats are smarter than dogs”) if ret: print(ret.group()) # Cats are smarter than dogs print(ret.group(1)) # Cats print(ret.group(2)) # smarter else: print(“None”)

<a name="URDNF"></a>
### findall方法

- 作用:在字符串中找到正则表达式所匹配的所有子串,并返回一个列表。如果有多个匹配模式,则返回元组列表;如果没有找到匹配的,则返回空列表
- 语法格式:
   - 方式一:`re.findall(pattern, string, flags=0)`
   - 方式二:`pattern.findall(string[, pos[, endpos]])`
      - pos:指定字符串的起始位置,默认为0
      - endpos:指定字符串的结束位置,默认为字符串的长度
   - 注意:返回值是列表,没有group方法
```python
import re

ret = re.findall(r'\d+', "python = 9999, c = 7890, c++ = 12345")
print(ret)  # ['9999', '7890', '12345']

# 多个匹配模式,返回元组列表
result = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
print(result)  # [('width', '20'), ('height', '10')]

finditer方法

  • 和findall类似,在字符串中找到正则表达式所匹配的所有子串,区别是返回一个迭代器
  • 语法格式:re.finditer(pattern, string, flags=0) ```python import re

it = re.finditer(r”\d+”, “12a32bc43jf3”) for match in it: print(match.group()) # 12 32 43 3

<a name="BM2nU"></a>
### sub方法

- 作用:替换字符串中的匹配项
- 语法格式:`re.sub(pattern, repl, string, count=0, flags=0)`
   - pattern:匹配的正则表达式
   - repl:替换的字符串,也可为一个函数
   - string:要被查找替换的原始字符串
   - count:替换的最大次数,默认值为0,表示替换所有的匹配
   - flags:编译时用的匹配模式,数字形式
```python
import re

phone = "2004-959-559 # 这是一个电话号码"

# 删除注释
num = re.sub(r'#.*$', "", phone)
print(num)  # 2004-959-559

# 移除非数字的内容
num = re.sub(r'\D', "", phone)
print(num)  # 2004959559


ret = re.sub(r'\d+', '998', 'python 997')
print(type(ret))  # <class 'str'>
print(ret)  # python 998


def add(temp):
    str_num = temp.group()
    num = int(str_num) + 5
    return str(num)


ret = re.sub(r'\d+', add, 'python 997')
print(ret)  # python 1002

ret = re.sub(r'\d+', lambda x: str(int(x.group()) + 5), 'python 997')
print(ret)  # python 1002

split方法

  • 作用:按照能够匹配的子串将字符串分割后,返回列表
  • 语法格式:re.split(pattern, string, maxsplit=0, flags=0)
    • pattern:匹配的正则表达式
    • string:待匹配的字符串
    • maxsplit:分割次数,默认值为0,表示不限制次数
    • flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等 ```python import re

ret = re.split(r”:| “, “info:xiaoZhang 33 shandong”) print(ret) # [‘info’, ‘xiaoZhang’, ‘33’, ‘shandong’]

<a name="xWDC9"></a>
### compile方法

- 作用:用于编译震泽表达式,生成一个正则表达式对象,供match()和search()这两个方法使用
- 语法格式:`re.compile(pattern[, flags])`
   - pattern:一个字符串形式的正则表达式
   - flags:标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等
```python
import re

pattern = re.compile(r'\d+')  # 查找数字
print(pattern.findall('runoob 123 google 456'))  # ['123', '456']
print(pattern.findall('run88oob123google456', 0, 10))  # ['88', '12']

贪婪和非贪婪

  • Python里数量词默认是贪婪的,总是尝试匹配尽可能多的字符;非贪婪则相反,总是尝试匹配尽可能少的字符
  • 在 ‘*’、’+’、’?’、’{m,n}’ 后面加上 ?,使贪婪变成非贪婪
  • 举例

image.png
说明:第一个例子中,’+’ 会从字符串的开始处抓取满足模式的最长字符,而 ‘\d+’ 只需要一位字符就可以匹配,所以它匹配了数字4,而 ‘.+’ 则匹配了从字符串开始处到这个第一位数字4之前的所有字符。第二个例子中,’+?’ 会从字符串的开始处抓取满足模式的最短字符,那就是一个也不匹配,所以后面的 ‘\d+’ 匹配了234

import re

print(re.match(r"aa(\d+)", "aa2343ddd").group(1))  # 2343
print(re.match(r"aa(\d+?)", "aa2343ddd").group(1))  # 2
print(re.match(r"aa(\d+)ddd", "aa2343ddd").group(1))  # 2343
print(re.match(r"aa(\d+?)ddd", "aa2343ddd").group(1))  # 2343

r的作用

  • 正则表达式里使用 ‘\’ 作为转义字符,这就可能造成反斜杠困扰。如果你需要匹配文本中的字符 ‘\’,那么使用编程语言表示的正则表达式里将需要四个反斜杠 ‘\\‘,前两个和后两个分别用于在编程语言里转义成一个反斜杠,转换后的得到的两个反斜杠再在正则表达式里专业成一个反斜杠
  • Python中字符串前面加上 r 表示原生字符串,有了原生字符串,再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观
  • 注意:r 只服务与 ‘\’,不对其他进行转义 ```python import re

mm = “c:\a\b\c”

print(mm) # c:\a\b\c

print(re.match(“c:\\“, mm).group()) # c:\

print(re.match(“c:\\a”, mm).group()) # c:\a

print(re.match(r”c:\a”, mm).group()) # c:\a

print(re.match(r”c:\“, mm).group()) # c:\

print(re.match(r”c:\a”, mm).group())

AttributeError: ‘NoneType’ object has no attribute ‘group’

<a name="WYrIQ"></a>
## 正则表达式的可选标志
正则表达式可以包含一些可选标志修饰符来控制匹配的模式,修饰符被指定为一个可选的标志,多个标志可以通过 | 来指定,例如 re.I | re.M 被设置成 I 和 M 标志<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/12692524/1655862658302-0d59808b-7184-4404-b743-1bed1760ebf0.png#clientId=u0be3d574-bd1e-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=278&id=udf3060e2&margin=%5Bobject%20Object%5D&name=image.png&originHeight=417&originWidth=932&originalType=binary&ratio=1&rotation=0&showTitle=false&size=39237&status=done&style=none&taskId=u7911df7f-505b-4e8d-acc7-5cd900804c2&title=&width=621.3333333333334)
```python
import re

ret = re.match(r'a', 'A', re.I)  # 不区分大小写
print(ret.group())

ret = re.match(r'.bc', '\nbc', re.S)  # 使.匹配包括换行在内的所有字符
print(ret.group())