Python 正则表达式(Regular Expression)是一种用于匹配、查找、替换字符串的强大模式语言,通过特殊的语法规则定义字符串的匹配模式,广泛应用于文本验证(如邮箱、手机号)、信息提取(如从文本中抓取值)、字符串替换等场景。Python 中通过内置的 re 模块提供对正则表达式的支持。
一、正则表达式的核心概念
正则表达式本质是一个字符串模式,用于描述“什么样的字符串符合规则”。例如,模式 r"^\d{3}-\d{8}$" 可匹配“010-12345678”这样的固定电话格式。
- 元字符:正则表达式中具有特殊含义的字符(如
.、*、+等),是构建模式的核心。 - 普通字符:除元字符外的字符(如字母、数字、空格),仅匹配自身。
二、正则表达式基本语法(元字符)
掌握元字符是学习正则的基础,以下是常用元字符及含义:
1. 字符匹配
| 元字符 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
. |
匹配任意单个字符(除换行符 \n) |
a.c |
abc、a1c、a&c |
[] |
匹配括号内的任意单个字符 | a[0-9]c |
a0c、a5c(0-9的数字) |
[^] |
匹配不在括号内的任意单个字符 | a[^0-9]c |
abc、a&c(非数字) |
\d |
匹配任意数字(等价于 [0-9]) |
a\d |
a1、a9 |
\D |
匹配任意非数字(等价于 [^0-9]) |
a\D |
aa、a! |
\w |
匹配字母、数字、下划线([a-zA-Z0-9_]) |
\w\w |
ab、12、a_ |
\W |
匹配非字母、数字、下划线 | \W\W |
!!、@# |
\s |
匹配空白字符(空格、\t、\n等) |
a\sb |
a b、a\tb(a和b之间有空白) |
\S |
匹配非空白字符 | a\Sb |
a1b、a@b |
2. 数量限定(修饰前一个字符的出现次数)
| 元字符 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
* |
前一个字符出现0次或多次(贪婪匹配) | ab* |
a(b出现0次)、ab、abb |
+ |
前一个字符出现1次或多次(贪婪匹配) | ab+ |
ab、abb(至少1个b) |
? |
前一个字符出现0次或1次 | ab? |
a、ab(最多1个b) |
{n} |
前一个字符恰好出现n次 | a{2} |
aa(刚好2个a) |
{n,} |
前一个字符出现至少n次 | a{2,} |
aa、aaa(≥2个a) |
{n,m} |
前一个字符出现n到m次(含n和m) | a{1,3} |
a、aa、aaa |
3. 边界匹配(限定字符串的位置)
| 元字符 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
^ |
匹配字符串开头(多行模式下匹配每行开头) | ^abc |
abc(字符串以abc开头) |
$ |
匹配字符串结尾(多行模式下匹配每行结尾) | abc$ |
abc(字符串以abc结尾) |
\b |
匹配单词边界(单词与非单词的交界) | \bhello\b |
hello(独立单词,如 hello! 中的hello) |
\B |
匹配非单词边界 | \Bhello\B |
xhelloy 中的 hello(被单词字符包围) |
4. 逻辑与分组
| 元字符 | 含义 | 示例 | 匹配结果 |
|---|---|---|---|
| |
逻辑“或”,匹配两边任意一个模式 | abc|def |
abc 或 def |
() |
分组,将括号内的模式视为一个整体 | (ab)+ |
ab、abab(ab重复1次或多次) |
\num |
引用第num个分组的匹配结果(num为1开始的整数) | (a)\1 |
aa(第一个分组匹配a,\1引用该结果) |
5. 贪婪与非贪婪匹配
- 贪婪匹配:默认行为,尽可能匹配最长的字符串(如
*、+、{n,m})。 - 非贪婪匹配:在数量限定符后加
?,尽可能匹配最短的字符串。
示例:
import re
text = "aabbaabb"
# 贪婪匹配:.* 尽可能匹配最长的字符串(从第一个a到最后一个b)
print(re.match(r"a.*b", text).group()) # → "aabbaabb"
# 非贪婪匹配:.*? 尽可能匹配最短的字符串(从第一个a到第一个b)
print(re.match(r"a.*?b", text).group()) # → "aabb"
三、Python re 模块常用函数
re 模块提供了一系列函数用于正则匹配,核心函数如下:
1. re.match(pattern, string, flags=0)
- 功能:从字符串开头匹配模式,若开头不匹配则返回
None。 - 返回值:匹配对象(
Match),若匹配失败返回None。 - 示例:
import re
# 匹配以"hello"开头的字符串
result = re.match(r"hello", "hello world")
print(result.group()) # → "hello"(匹配成功,返回匹配内容)
# 开头不匹配,返回None
result = re.match(r"world", "hello world")
print(result) # → None
2. re.search(pattern, string, flags=0)
- 功能:在整个字符串中查找第一个匹配(不限于开头),找到则返回匹配对象,否则返回
None。 - 区别于
match:match仅从开头匹配,search搜索整个字符串。 - 示例:
# 在字符串中查找"world"(不在开头)
result = re.search(r"world", "hello world")
print(result.group()) # → "world"
3. re.findall(pattern, string, flags=0)
- 功能:在字符串中查找所有匹配,返回包含所有匹配内容的列表(无匹配则返回空列表)。
- 示例:
# 提取字符串中所有数字
text = "age: 18, score: 95, weight: 60"
nums = re.findall(r"\d+", text) # \d+ 匹配1个或多个数字
print(nums) # → ['18', '95', '60']
4. re.finditer(pattern, string, flags=0)
- 功能:与
findall类似,但返回迭代器(每个元素是Match对象),适合处理大量匹配结果(节省内存)。 - 示例:
text = "a1 b2 c3"
matches = re.finditer(r"\d", text) # 查找所有单个数字
for m in matches:
print(m.group()) # 依次输出:1、2、3
5. re.sub(pattern, repl, string, count=0, flags=0)
- 功能:用
repl替换字符串中所有匹配pattern的子串,返回替换后的新字符串。 - 参数:
count为最大替换次数(默认0表示全部替换)。 - 示例:
# 将所有数字替换为"*"
text = "a1 b2 c3"
new_text = re.sub(r"\d", "*", text)
print(new_text) # → "a* b* c*"
# 只替换前2个数字
new_text2 = re.sub(r"\d", "*", text, count=2)
print(new_text2) # → "a* b* c3"
6. re.split(pattern, string, maxsplit=0, flags=0)
- 功能:按匹配
pattern的子串分割字符串,返回分割后的列表。 - 参数:
maxsplit为最大分割次数(默认0表示全部分割)。 - 示例:
# 按逗号或空格分割字符串
text = "a,b c,d"
parts = re.split(r"[, ]", text) # 匹配逗号或空格
print(parts) # → ['a', 'b', 'c', 'd']
7. re.compile(pattern, flags=0)
- 功能:编译正则表达式模式为正则对象(
RegexObject),可重复使用(提高效率,尤其多次匹配时)。 - 示例:
# 编译模式(只做一次)
pattern = re.compile(r"\d+")
# 重复使用编译后的对象
print(pattern.findall("age: 18")) # → ['18']
print(pattern.findall("score: 95")) # → ['95']
四、分组与捕获(() 的用法)
() 用于将模式分组,可通过匹配对象的 group() 方法提取分组内容:
group(0)或group():返回整个匹配内容。group(1)、group(2)...:返回第1、2...个分组的内容。
示例:提取邮箱中的用户名和域名
import re
email = "user@example.com"
# 分组匹配:(用户名)@(域名)
pattern = r"(\w+)@(\w+\.\w+)"
result = re.match(pattern, email)
print(result.group(0)) # 整个匹配 → "user@example.com"
print(result.group(1)) # 第一个分组(用户名)→ "user"
print(result.group(2)) # 第二个分组(域名)→ "example.com"
print(result.groups()) # 所有分组组成的元组 → ("user", "example.com")
五、常用修饰符(flags 参数)
修饰符用于改变正则匹配的行为,常用值:
re.IGNORECASE(re.I):忽略大小写匹配。re.DOTALL(re.S):让.匹配包括换行符\n在内的所有字符。re.MULTILINE(re.M):让^和$匹配每行的开头和结尾(而非整个字符串)。
示例:忽略大小写匹配
import re
# 不忽略大小写:无法匹配大写的Hello
print(re.match(r"hello", "Hello")) # → None
# 忽略大小写:成功匹配
print(re.match(r"hello", "Hello", flags=re.IGNORECASE).group()) # → "Hello"
六、实际应用场景
1. 验证手机号(中国大陆手机号:11位数字,以1开头)
def is_valid_phone(phone):
pattern = r"^1\d{10}$" # ^1:以1开头;\d{10}:10个数字;$:结尾
return bool(re.match(pattern, phone))
print(is_valid_phone("13812345678")) # → True
print(is_valid_phone("1234567890")) # → False(不足11位)
2. 提取HTML中的所有链接(<a href="url">)
html = '''
<a href="https://www.baidu.com">百度</a>
<a href="https://www.google.com">谷歌</a>
'''
# 分组提取href的值(""中的内容)
urls = re.findall(r'href="(.*?)"', html) # .*? 非贪婪匹配,避免匹配到多个链接
print(urls) # → ['https://www.baidu.com', 'https://www.google.com']
3. 清洗文本(去除所有标点符号)
import string
text = "Hello, World! It's a test."
# 匹配所有标点符号(string.punctuation包含所有标点)
clean_text = re.sub(rf"[{string.punctuation}]", "", text)
print(clean_text) # → "Hello World Its a test"
七、注意事项
1.转义字符:若需匹配元字符本身(如 .、*),需用 \ 转义(如 \. 匹配 .)。
# 匹配IP地址中的点(需转义)
print(re.match(r"192\.168\.1\.1", "192.168.1.1").group()) # → "192.168.1.1"
2.原始字符串:正则模式建议用原始字符串(r"模式"),避免 \ 被Python解释器转义(如 r"\d" 正确表示 \d,而非 d)。
3.性能问题:复杂的正则表达式可能效率较低,尤其是处理大文本时,建议:
- 用
re.compile编译模式复用。 - 避免过度使用贪婪匹配(必要时用非贪婪)。
总结
正则表达式是处理字符串的强大工具,Python 的 re 模块提供了完整支持。核心知识点包括:
- 元字符:字符匹配、数量限定、边界匹配、分组等。
- 常用函数:
match(开头匹配)、search(全局首匹配)、findall(所有匹配)、sub(替换)等。 - 分组:通过
()提取子串,灵活获取关键信息。
掌握正则表达式能极大提升文本处理效率,建议结合实际场景(如验证、提取、清洗)多练习,逐步熟悉元字符的组合使用。
正则表达式
正则表达式这东西,你说它简单它也简单,你说它难吧,确实不容易。为什么?这东西就是死记硬背的。背过了相关的语法,使用起来就so easy。但记不熟语法,就犯难了。
正则表达式简介
正则表达式,是一个特殊的字符序列,又称规则表达式(英语:Regular Expression,在代码中常简写为regex、regexp 或RE),本质而言是一种小型的,高度专业化的编程语言。 Python 自1.5版本起增加了re 模块,re 模块使Python语言拥有全部的正则表达式功能。
正则语法表
这个你背不过,再好的教程看了也没用。如何巧记?我们需要对其进行分类。
- 开头结尾
这一对标签,大家都不会陌生…
| 模式 | 描述 |
|---|---|
| ^ | 从整个字符串开头的地方匹配 |
| $ | 从整个字符串的结尾开始匹配 |
- 模糊匹配
| 模式 | 描述 |
|---|---|
| . | 匹配任意字符,除了换行符 |
| ? | 重复匹配?号前面0个或1个由前面的正则表达式定义的片段,非贪婪方式(?写在数量词的之后) |
| * | 重复匹配*号前面0个或多个的表达式。{0, 无穷大} |
| + | 重复匹配+号前面1个或多个的表达式。{1,无穷大} |
| a丨b | 匹配a或b |
- 关于括号
| 模式 | 描述 |
|---|---|
| {} | 表示匹配"{}"前边的字符 指定个数为"{}"里边的数值{最小此时,最大次数} |
| [] | 表示一个字符集,它常被用来指定一个字符类别,字符可以单个列出,也可以用“-”号分隔的两个给定字符来表示一个字符区间 |
| () | 分组 将括号中的内容 当作整体来对待 |
\反斜杠的应用
| 模式 | 描述 |
|---|---|
| \w | 匹配字母数字及下划线 |
| \W | 匹配非字母数字及下划线 |
| \s | 匹配任意空白字符,等价于 [\t\n\r\f]. |
| \S | 匹配任意非空字符 |
| \d | 匹配任意数字,等价于 [0-9]. |
| \D | 匹配任意非数字 |
| \A | 匹配字符串开始^ |
| \Z | 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。$ |
| \z | 匹配字符串结束 |
| \G | 匹配最后匹配完成的位置。 |
| \b | 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。 |
| \B | 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。 |
| \n, \t, 等. | 匹配一个换行符。匹配一个制表符。等 |
| \1…\9 | 匹配第n个分组的内容。 |
| \10 | 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。 |
- 其他
| 模式 | 描述 |
|---|---|
| (?imx) | 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。 |
| (?-imx) | 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。 |
| (?: re) | 类似 (…), 但是不表示一个组 |
| (?imx: re) | 在括号中使用i, m, 或 x 可选标志 |
| (?-imx: re) | 在括号中不使用i, m, 或 x 可选标志 |
| (?#…) | 注释. (?# 正则中的注释) |
| (?= re) | 前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。 |
| (?! re) | 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功 |
| (?> re) | 匹配的独立模式,省去回溯。 |
re模块用法
re.(function)(pattern[, flags]) pattern : 一个字符串形式的正则表达式 flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
- re.I 忽略大小写
- re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
- re.M 多行模式
- re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
- re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
- re.X 为了增加可读性,忽略空格和 # 后面的注释
- findall() (即:全部找到,返回的是一个列表)
findall(string[, pos[, endpos]]) 参数:
- string : 待匹配的字符串。
- pos : 可选参数,指定字符串的起始位置,默认为 0。
- endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。
import re
s = 'helloworld hellobeijing'
ret = re.findall('hello\S+',s)
print(ret)
['helloworld', 'hellobeijing']
- finditer()
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。 re.finditer(pattern, string, flags=0) 参数:
| 参数 | 描述 |
|---|---|
| pattern | 匹配的正则表达式 |
| string | 要匹配的字符串。 |
| flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等 |
- search() 与 match()
相同点:
- 语法:re.search/match(pattern, string, flags=0)
- 函数参数说明:
| 参数 | 描述 |
|---|---|
| pattern | 匹配的正则表达式 |
| string | 要匹配的字符串。 |
| flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等 |
- 可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。
| 匹配方法 | 描述 |
|---|---|
| group(num=0) | 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组 |
| groups() | 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号 |
| start([group]) | 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0 |
| end([group]) | 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0 |
| span([group]) | 方法返回 (start(group), end(group) |
import re
# re.search
ret = re.search('h..','hello hello world')
print(ret) # 输出结果:<_sre.SRE_Match object; span=(0, 3), match='hel'>
ret1 = re.search('h..','hello hello world').group()
print(ret1) # 输出结果:hel 只输出第一个符合条件的结果
# re.match
ret = re.match('asd','asdhskdjfksji')
print(ret) # 输出结果:<_sre.SRE_Match object; span=(0, 3), match='asd'>返回的是一个对象。
ret1 = re.match('asd','asdhskdjfasdksjiasd').group()
print(ret1) # 输出结果:asd 调用.group()方法,只返回匹配的第一个结果。
不同点:
- re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None
- re.search匹配整个字符串,直到找到一个匹配
# re.search
s = 'helloworld hellobeijing'
ret = re.search('hellob\S+',s)
print(ret)
<re.Match object; span=(11, 23), match='hellobeijing'>
# re.match
s = 'helloworld hellobeijing'
ret = re.match('hellob\S+',s)
print(ret)
None
- split() 分隔符 对比字符串里边的split方法。
split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
re.split(pattern, string[, maxsplit=0, flags=0])
| 参数 | 描述 |
|---|---|
| pattern | 匹配的正则表达式 |
| string | 要匹配的字符串。 |
| maxsplit | 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。 |
| flags | 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志 |
import re
s = 'helloworld hellobeijing'
ret = re.split('hello',s)
print(ret)
['', 'world ', 'beijing']
- sub() 替换;类似字符串中的replace()方法。
re.sub用于替换字符串中的匹配项。 语法: re.sub(pattern, repl, string, count=0, flags=0) 参数:
- pattern : 正则中的模式字符串。
- repl : 替换的字符串,也可为一个函数。
- string : 要被查找替换的原始字符串。
- count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
import re
s = 'helloworld hellobeijing'
ret = re.sub('hello','goodbye',s)
print(ret)
goodbyeworld goodbyebeijing
- compile(strPattern[,flag]): 这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。 语法格式为: re.compile(pattern[, flags]) 参数: pattern : 一个字符串形式的正则表达式
- flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:
- re.I 忽略大小写
- re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
- re.M 多行模式
- re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
- re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
- re.X 为了增加可读性,忽略空格和 # 后面的注释
import re
pattern = re.compile('he.{3}')
pattern.match(s)
<re.Match object; span=(0, 5), match='hello'>
正则练习
import re
1 查找第一个匹配串
s = 'i love python very much'
pat = 'python'
r = re.search(pat,s)
print(r.span()) #(7,13)
2 查找所有1
s = '山东省潍坊市青州第1中学高三1班'
pat = '1'
r = re.finditer(pat,s)
for i in r:
print(i)
# <re.Match object; span=(9, 10), match='1'>
# <re.Match object; span=(14, 15), match='1'>
3 \d匹配数字[0-9]
s = '一共20行代码运行时间13.59s'
pat = r'\d+' # +表示匹配数字(\d表示数字的通用字符)1次或多次
r = re.findall(pat,s)
print(r)
# ['20', '13', '59']
我们想保留13.59而不是分开,请看4
4 ?表示前一个字符匹配0或1次
s = '一共20行代码运行时间13.59s'
pat = r'\d+\.?\d+' # ?表示匹配小数点(\.)0次或1次
r = re.findall(pat,s)
print(r)
# ['20', '13.59']
5 ^匹配字符串的开头
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'^[emrt]' # 查找以
r = re.findall(pat,s)
print(r)
# [],因为字符串的开头是字符`T`,不在emrt匹配范围内,所以返回为空
6 re.I 忽略大小写
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'^[emrt]' # 查找以
r = re.compile(pat,re.I).search(s)
print(r)
# <re.Match object; span=(0, 1), match='T'> 表明字符串的开头在匹配列表中
7 使用正则提取单词
这是不准确版本,请参看第9个
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s[a-zA-Z]+'
r = re.findall(pat,s)
print(r) #[' module', ' provides', ' regular', ' expression', ' matching', ' operations', ' similar', ' to', ' those', ' found', ' in', ' Perl']
8 只捕获单词,去掉空格
使用()捕获,这是不准确版本,请参看第9个
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s([a-zA-Z]+)'
r = re.findall(pat,s)
print(r) #['module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']
9 补充上第一个单词
上面第8,看到提取单词中未包括第一个单词,使用?表示前面字符出现0次或1次,但是此字符还有表示贪心或非贪心匹配含义,使用时要谨慎。
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s?([a-zA-Z]+)'
r = re.findall(pat,s)
print(r) #['This', 'module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']
10 使用split函数直接分割单词
使用以上方法分割单词,不是简洁的,仅仅为了演示。分割单词最简单还是使用split函数。
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s+'
r = re.split(pat,s)
print(r) # ['This', 'module', 'provides', 'regular', 'expression', 'matching', 'operations', 'similar', 'to', 'those', 'found', 'in', 'Perl']
11 提取以m或t开头的单词,忽略大小写
下面出现的结果不是我们想要的,原因出在 ?上!
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s?([mt][a-zA-Z]*)' # 查找以
r = re.findall(pat,s)
print(r) # ['module', 'matching', 'tions', 'milar', 'to', 'those']
12 使用^查找字符串开头的单词
综合11和12得到所有以m或t开头的单词
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'^([mt][a-zA-Z]*)\s' # 查找以
r = re.compile(pat,re.I).findall(s)
print(r) # ['This']
13 先分割,再查找满足要求的单词
使用match表示是否匹配
s = 'This module provides regular expression matching operations similar to those found in Perl'
pat = r'\s+'
r = re.split(pat,s)
res = [i for i in r if re.match(r'[mMtT]',i)]
print(res) # ['This', 'module', 'matching', 'to', 'those']
14 贪心匹配
尽可能多的匹配字符
content='<h>ddedadsad</h><div>graph</div>bb<div>math</div>cc'
pat=re.compile(r"<div>(.*)</div>") #贪婪模式
m=pat.findall(content)
print(m) # ['graph</div>bb<div>math']
15 非贪心匹配
与14相比,仅仅多了一个问号(?),得到结果完全不同。
content='<h>ddedadsad</h><div>graph</div>bb<div>math</div>cc'
pat=re.compile(r"<div>(.*?)</div>") #贪婪模式
m=pat.findall(content)
print(m) # ['graph', 'math']
与14比较可知,贪心匹配和非贪心匹配的区别,后者是字符串匹配后立即返回,见好就收。
16 含有多种分割符
使用split函数
content = 'graph math,,english;chemistry' # 这种
pat=re.compile(r"[\s\,\;]+") #贪婪模式
m=pat.split(content)
print(m) # ['graph', 'math', 'english', 'chemistry']
17 替换匹配的子串
sub函数实现对匹配子串的替换
content="hello 12345, hello 456321"
pat=re.compile(r'\d+') #要替换的部分
m=pat.sub("666",content)
print(m) # hello 666, hello 666
18 爬取百度首页标题
import re
from urllib import request
#爬虫爬取百度首页内容
data=request.urlopen("http://www.baidu.com/").read().decode()
#分析网页,确定正则表达式
pat=r'<title>(.*?)</title>'
result=re.search(pat,data)
print(result) <re.Match object; span=(1358, 1382), match='<title>百度一下,你就知道</title>'>
result.group() # 百度一下,你就知道
19 常用元字符总结复习
. 匹配任意字符
^ 匹配字符串始位置
$ 匹配字符串中结束的位置
* 前面的原子重复0次1次多次
? 前面的原子重复一次或者0次
+ 前面的原子重复一次或多次
{n} 前面的原子出现了 n 次
{n,} 前面的原子至少出现 n 次
{n,m} 前面的原子出现次数介于 n-m 之间
( ) 分组,需要输出的部分
20 常用通用字符总结复习
\s 匹配空白字符
\w 匹配任意字母/数字/下划线
\W 和小写 w 相反,匹配任意字母/数字/下划线以外的字符
\d 匹配十进制数字
\D 匹配除了十进制数以外的值
[0-9] 匹配一个0-9之间的数字
[a-z] 匹配小写英文字母
[A-Z] 匹配大写英文字母
最全的常用正则表达式大全
一、校验数字的表达式
- 数字:^[0-9]*$
- n位的数字:^\d{n}$
- 至少n位的数字:^\d{n,}$
- m-n位的数字:^\d{m,n}$
- 零和非零开头的数字:^(0|[1-9][0-9]*)$
- 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$
- 带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})?$
- 正数、负数、和小数:^(-|+)?\d+(.\d+)?$
- 有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
- 有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
- 非零的正整数:^[1-9]\d$ 或 ^([1-9][0-9]){1,3}$ 或 ^+?[1-9][0-9]*$
- 非零的负整数:^-[1-9][]0-9″$ 或 ^-[1-9]\d$
- 非负整数:^\d+$ 或 ^[1-9]\d*|0$
- 非正整数:^-[1-9]\d*|0$ 或 ^((-\d+)|(0+))$
- 非负浮点数:^\d+(.\d+)?$ 或 ^[1-9]\d.\d|0.\d[1-9]\d|0?.0+|0$
- 非正浮点数:^((-\d+(.\d+)?)|(0+(.0+)?))$ 或 ^(-([1-9]\d.\d|0.\d[1-9]\d))|0?.0+|0$
- 正浮点数:^[1-9]\d.\d|0.\d[1-9]\d$ 或 ^(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9]))$
- 负浮点数:^-([1-9]\d.\d|0.\d[1-9]\d)$ 或 ^(-(([0-9]+.[0-9][1-9][0-9])|([0-9][1-9][0-9].[0-9]+)|([0-9][1-9][0-9])))$
- 浮点数:^(-?\d+)(.\d+)?$ 或 ^-?([1-9]\d.\d|0.\d[1-9]\d|0?.0+|0)$
二、校验字符的表达式
- 汉字:^[\u4e00-\u9fa5]{0,}$
- 英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
- 长度为3-20的所有字符:^.{3,20}$
- 由26个英文字母组成的字符串:^[A-Za-z]+$
- 由26个大写英文字母组成的字符串:^[A-Z]+$
- 由26个小写英文字母组成的字符串:^[a-z]+$
- 由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
- 由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
- 中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
- 中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
- 可以输入含有^%&’,;=?$\”等字符:[^%&',;=?$\x22]+
- 禁止输入含有~的字符:[^~\x22]+
三、特殊需求表达式
-
Email地址:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$
-
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
-
InternetURL:[a-zA-z]+://[^\s] 或 ^http://([\w-]+.)+[\w-]+(/[\w-./?%&=])?$
-
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
-
电话号码(“XXX-XXXXXXX”、”XXXX-XXXXXXXX”、”XXX-XXXXXXX”、”XXX-XXXXXXXX”、”XXXXXXX”和”XXXXXXXX):^($$\d{3,4}-)|\d{3.4}-)?\d{7,8}$
-
国内电话号码(0511-4405222、021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
-
身份证号(15位、18位数字):^\d{15}|\d{18}$
-
短身份证号码(数字、字母x结尾):^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
-
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
-
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线):^[a-zA-Z]\w{5,17}$
-
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间):^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$
-
日期格式:^\d{4}-\d{1,2}-\d{1,2}
-
一年的12个月(01~09和1~12):^(0?[1-9]|1[0-2])$
-
一个月的31天(01~09和1~31):^((0?[1-9])|((1|2)[0-9])|30|31)$