引言
在开发中会有大量的字符串处理工作,其中经常会涉及到字符串格式的校验。
如何把一个 字符串的特征或者规则告诉计算机,让计算机也能知道我们要描述的是什么样的东西,这个描述的语法就是正则表达式。
概述
正则表达式,又称正规表示式、正规表示法、规则表达式、常规表示法(英文:Regular Expression ,在代码中常简写为regex、regexp或RE)。是计算机科学的一个概念。
正则表达式使用单个字符串来描述、匹配一些列某个句法规则的字符串。
在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。
Regular Expression 即“描述某种规则的表达式”。
re模块操作
在Python中使用正则表达式的工具为re模块。
re模块的使用
import re
# 使用match方法进行匹配操作
result = re.match(正则表达式, 要匹配的字符串)
# 如果上一步匹配到数据,可以使用group方法来提取数据
result.group()
re.match
是用来进行正则匹配检查的方法,从左到右去匹配
若字符串匹配正则表达式,则match方法返回匹配对象(Match Object)
否则返回None(注意不是空字符串"")
匹配对象Match Object具有group方法,用来返回字符串的匹配部分。
re模块的高级用法
search
在字符串当中进行搜索。
import re
ret = re.search(r"\d+", "阅读数为:9999")
ret.group()
运行结果:'9999'
search方法,从左到右找到第一个匹配的检查就结束,只能拿到第一个。
findall
拿到正则匹配的所有结果
findall返回的是列表类型,显示所有匹配结果
import re
ret = re.findall(r"\d+", "python = 9999, c = 7890, c++= 1234")
print(ret)
运行结果:['9999', '7890', '1234']
sub
sub方法是将匹配到的数据进行替换
sub(规则部分, 要替换的值, 处理的字符串)
返回新的结果
import re
ret = re.sub(r"\d+", "998", "python = 997")
print(ret)
运行结果:'python = 998'
要替换的值可以接收一个函数,来执行特定的规则
import re
def replace(result):
# result为正则匹配到的值,所以其有group方法
r = int(result.group()) + 50
# 该函数一定要有返回值,返回的只能是字符串类型
return str(r)
ret = re.sub(r"\d+", replace, "python = 1000, php = 0")
print(ret)
运行结果:'python = 1050, php = 50'
split
根据匹配进行切割字符串,并返回一个列表
import re
ret = re.split(r":| ", "info:ly 26 beijing")
print(ret)
运行结果: ['info', 'ly', '26', 'beijing']
表示字符
正则表达式的但字符匹配
字符 | 功能 |
---|---|
. | 匹配任意1个字符(除了\n) |
[] | 匹配[]中列举的字符 |
\d | 匹配数字,即0-9 |
\D | 匹配非数字 |
\s | 匹配空白字符,即 空格、tab键、\t、\n、 \r |
\S | 匹配非空白 |
\w | 匹配单词字符,即a-z、A-Z、0-9、_ |
\W | 匹配非单词字符 |
手机号校验
import re
re.match("1[35678]\d\d\d\d\d\d\d\d\d", "13200000000")
[]用法特点:
- 预定义的集合中不能满足个人需求时使用
-
[^345678]
对[]中的所有字符取反 -
[a-z]
"-"表示的是一个范围值 - \d == [0-9]
- \D == [^0-9]
- \w == [a-zA-Z0-9_]
- \W == [^a-zA-Z0-9_]
表示数量
匹配多个字符的相关格式
字符 | 功能 |
---|---|
* | 匹配前一个字符出现0次或者无限次,即 可有可无 |
+ | 匹配前一个字符出现1次或者无限次,即 至少有1次 |
? | 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
{m} | 匹配前一个字符出现m次 |
{m,} | 匹配前一个字符至少出现m次 |
{m, n} | 匹配前一个字符出现从m到n次 |
手机号校验优化
import re
re.match("1[35678]\d{9}", "13245678910")
原始字符串描述
import re
mm = "C:\\a\\b\\c"
ret = re.match(r"C:\\a", mm).group()
print(ret)
输出结果:C:\a
以后再去写正则表达式的时候,正则的规则前面通常要加上r
,忽略掉里面需要转义的地方。
表示边界
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
\b | 匹配一个单词的边界 |
\B | 匹配非单词的边界 |
手机校验再次优化
import re
re.match(r"^1[35678]\d{9}$", "13245678910")
因为match方法就是从左到右匹配的,所以^在match方法中体现不是很明显
匹配分组
字符 | 功能 |
---|---|
| | 匹配左右任意一个表达式 |
(ab) | 将括号中的字符作为一个分组 |
\num |
引用分组num匹配到字符串 |
(?P<name>) | 分组其别名 (<>定义别名) |
(?P=name) | 引用别名为name分组匹配到的字符串 (=使用别名) |
匹配出0-100之间的数字
import re
# 使用|管道符
re.match(r"[1-9]\d?$|0$|100$", "88" )
# 简化
re.match(r"[1-9]?\d", "88")
邮箱匹配
re.match(r"\w{5, 20}+@(163|126|gmail|qq)\.(com|cn|net)$", "tangerine@qq.com")
贪婪和非贪婪
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符。
非贪婪则总是尝试匹配尽可能少的字符。
在*
、?
、+
、{m, n}
后面加上?
,使贪婪变成非贪婪。
# 贪婪
s = "This is a number 234-235-22-423"
ret = re.match(".+(\d+-\d+-\d+-\d+)", s)
ret.group(1)
'4-234-22-423'
# 非贪婪
ret = re.match(".+?(\d+-\d+-\d+-\d+)", s)
ret.group(1)
'234-235-22-423'
网友评论