在编写处理字符串的程序时,经常会有查找符合某些复杂规则的字符串的需要。正则表达式就是用于描述这些规则的工具。
一些常用的正则表达式语法
. 匹配除换行符 \n 之外的任何单字符
* 匹配前面的子表达式零次或多次
+ 匹配前面的子表达式一次或多次
? 匹配前面的子表达式零次或一次
{2} 匹配前面的子表达式2次
\s 匹配任何空白字符,包括空格、制表符等
[A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母
[0-9] 表示一个区间,匹配所有数字
$ 匹配到字符串结尾
re的使用
假设我们要从如下内容中匹配子字符串,匹配其中<a href=“https://www.baidu.com”>
<html>
<head>
<title> 百度 </title>
</head>
<body>
<p>
<a href="https://www.baidu.com"> 百度链接 </a></p>
<p>
<a href="https://image.baidu.com"> 百度链接 </a></p>
</body>
先来设计子表达式
<a 为固定内容,照抄得到: <a
<a href <a 与 href 之间存在其他字符(如空格),可以使用 \s ,同时数量未定,所以配合 *, 最后得到:<a\s*
href 为固定内容,照抄得到: <a\s*href
href = " 同理 href 与 = 之间, = 与 " 之间存在数量未定的空格, 最后得到:<a\s*href\s*=\s*"
链接 内容不定, 使用 . , 数量不定(至少有一个), 配合 +, 最后得到:<a\s*href\s*=\s*".+
> 为固定内容,照抄得到: <a\s*href\s*=\s*".+">
# re.search 扫描整个字符串并返回第一个成功的匹配
re.search('<a\s*href\s*=\s*".+">', data)
# re.compile 函数用于编译正则表达式。对于需要频繁使用到的正则表达式可以先编译,生成一个正则表达式对象,供 match() 等函数使用。
RE = re.compile(r'<a\s*href\s*=\s*".+">')
RE.search(data)
pattern = RE.search(data)
pattern.span() # .span() 可以获取匹配到内容的起始和截止位置
pattern.group() # .group() 可以获取匹配到的内容
# re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
RE.match(data)
# re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
RE.match(data)
re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
# re.findall 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
RE.findall(data)
# re.finditer 在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
links = RE.finditer(data)
for link in links: # 从迭代器中逐次取出数据赋予link
...
link
...
match 和 search 是匹配一次,而 findall 和 finditer 是匹配所有。
文件结构
project
│ BaiDu.html
│ RE.py
BaiDu.html
<html>
<head>
<title> 百度 </title>
</head>
<body>
<p>
<a href="https://www.baidu.com"> 百度链接 </a></p>
<p>
<a href="https://image.baidu.com"> 百度链接 </a></p>
</body>
RE.py
# -*- coding: UTF-8 -*-
import re
"""
正则表达式常用的基本语法
. 匹配除换行符 \n 之外的任何单字符
* 匹配前面的子表达式零次或多次
+ 匹配前面的子表达式一次或多次
? 匹配前面的子表达式零次或一次
{2} 匹配前面的子表达式2次
\s 匹配任何空白字符,包括空格、制表符等
[A-Z] 表示一个区间,匹配所有大写字母,[a-z] 表示所有小写字母
[0-9] 表示一个区间,匹配所有数字
$ 匹配到字符串结尾
"""
with open('BaiDu.html', 'r', encoding='utf-8') as fn: # 以"utf-8"的编码格式打开文件
data = fn.read() # 读取文件内的数据
# re.search 扫描整个字符串并返回第一个成功的匹配
print("re.search: |", re.search('<a\s*href\s*=\s*".+">', data))
# re.compile 函数用于编译正则表达式。对于需要频繁使用到的正则表达式可以先编译,生成一个正则表达式对象,供 match() 等函数使用。
RE = re.compile(r'<a\s*href\s*=\s*".+">')
pattern = RE.search(data)
print("re.search: |", pattern)
print(".span: |", pattern.span()) # .span() 可以获取匹配到内容的起始和截止位置
print(".group: |", pattern.group()) # .group() 可以获取匹配到的内容
# re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none
print("re.match: |", RE.match(data))
"""
re.match与re.search的区别
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。
"""
# re.findall 在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
print("re.findall: |", RE.findall(data))
# re.finditer 在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
links = RE.finditer(data)
for link in links: # 从迭代器中逐次取出数据赋予link
print("re.finditer: |", link)
"""
match 和 search 是匹配一次,而 findall 和 finditer 是匹配所有。
"""
执行结果
re.search: | <re.Match object; span=(68, 100), match='<a href="https://www.baidu.com">'>
re.search: | <re.Match object; span=(68, 100), match='<a href="https://www.baidu.com">'>
.span: | (68, 100)
.group: | <a href="https://www.baidu.com">
re.match: | None
re.findall: | ['<a href="https://www.baidu.com">', '<a href="https://image.baidu.com">']
re.finditer: | <re.Match object; span=(68, 100), match='<a href="https://www.baidu.com">'>
re.finditer: | <re.Match object; span=(129, 163), match='<a href="https://image.baidu.com">'>