文章目录
1 正则表达式是什么
Regular Expression, 又称规则表达式。
正则表达式,就是用事先定义好的一些特定字符(组合),组成一个“规则字符串”,这个“规则字符串”用来描述了一种字符串的匹配模式(pattern)。
正则的作用:可以用来检查一个串是否含有某种数据、将匹配的数据替换或者取出
2 在Python中需要通过正则表达式对字符串进行匹配的时候,可以使用一个模块,名字为re
2.1 re模块的使用过程:
# 导入re模块
import re
# 使用match方法进行匹配操作
result = re.match(正则表达式,要匹配的字符串)
# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
# 如果没有匹配 则result是None
result = re.search(正则表达式,要匹配的字符串)
# 如果上一步匹配到数据的话,可以使用group方法来提取数据
result.group()
# 如果没有匹配 则result是None
2.2 re模块示范例子:
import re
result = re.search(r"it","it.cn")
result.group()
result = re.match(r"it","it.cn")
result.group(
运行结果为:it
3. 匹配单个字字符 功能
. 匹配任意1个字符(除了\n)
[ ] 匹配[ ]中列举的字符
\d 匹配数字,即0-9
\D 匹配非数字,即不是数字
\s 匹配空白,即 空格,tab键
\S 匹配非空白
\w 匹配单词字符,即a-z、A-Z、0-9、_
\W 匹配非单词字符
4. 匹配多个字符
字符 功能
* 匹配前一个字符出现0次或者无限次,即可有可无 \d* 等价于\d{0,}
+ 匹配前一个字符出现1次或者无限次,即至少有1次 \d+ 等价于\d{1,}
? 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 \d?等价于\d{0,1}
{m} 匹配前一个字符出现m次
{m,n} 匹配前一个字符出现从m到n次配开头和结尾
5. 匹配开头结尾
字符 功能
^ 匹配字符串开头,开始位置,
虽然match自带匹配开始的属性 但是为了正则的语义完整 建议也加上^
$ 匹配字符串结尾,结束位置
匹配的是结束位置 而不是数据
6. 匹配分组
字符 功能
| 匹配左右任意一个表达式
(ab) 将括号中字符作为一个分组
\num 引用分组num匹配到的字符串
(?P<name>) 分组起别名
(?P=name) 引用别名为name分组匹配到的字符串
详解:
目的 -- 在正则中使用() 将感兴趣的数据从整体中提取出来 放到分组存储
等整体匹配成功返回的结果对象中 .group(分组编号)就可以获取对应分组中数据了
group(0) == group() 就是正则表达式整体匹配的结果
用户的分组编号从1开始
() 表示匹配数据并放入分组
.group(分组编号)就可以获取对应分组中数据了
| 表示匹配|左边或者右边的正则表达式
(|) 表示匹配分组中| 左边或者右边的表达式 并且放入分组中
eg:<html>hh</html> --- <标签名>数据</标签名>
判断左边的标签和右边的标签名是否一致 如果一致则提取中的数据
引用分组的方式
目的 在正则的某个位置想要使用前面某个分组的数据进行匹配
使用形式: \分组编号
<html><h1>www.itcast.cn</h1></html>
re.match(r"(<\w+)><(\w+)>(.*)</\2></\1>","<html><h1>www.baidu.com</h1></html>").group(1)
有名分组
在匹配分组的时候 使用一个名字 而不直接使用下标
设置分组名称 (?P<name>)
引用某个名称的分组的数据 (?P=name)
7. re模块函数
7.1 match()
从头开始匹配 如果某个字符不能满足匹配规则 将匹配失败 返回None
直到匹配完成 将匹配结果放入匹配结果对象中,从匹配结果对象中获取到匹配结果,matchobj.group()
result = re.match(正则, 数据)
if result:
print(result.group())
else:
print("匹配失败")
7.2 search()
从头开始查找 如果某个字符不能满足匹配规则 将继续往后面查找 并尝试继续匹配
如果查找完 都没有匹配上 则返回None
如果匹配成功 将匹配结果放入匹配结果对象中,从匹配结果对象中获取到匹配结果,matchobj.group()
result = re.search(正则,数据)
if result:
print(result.group())
else:
print("匹配失败")
eg:匹配出文章阅读的次数
#coding=utf-8
import re
ret = re.search(r"\d+", "阅读次数为 9999")
ret.group()
运行结果:'9999'
8. re模块高级用法
8.1 findall(正则,数据)
查找数据中所有 符合正则规则的 数据 通过列表返回
eg:需求:统计出python、c、c++相应文章阅读的次数
import re
ret = re.findall(r"\d+", "python = 9999, c = 7890, c++ = 12345")
print(ret)
运行结果:['9999', '7890', '12345']
8.2 sub(正则,替换的数据, 被替换的数据)
将匹配到的数据进行替换
返回值返回,被替换之后的数据结果 字符串 源字符串不变
参数2还可以是一个函数的名字
这个函数需要满足一下几个条件才可以被正则调用
必须要有一个参数 ----- 通过这个参数将正则的匹配对象传递进去
必须要有一个返回值 ----- 通过返回值 返回替换的数据
需求:将匹配到的阅读次数加1
方法1:
import re
ret = re.sub(r"\d+", '998', "python = 997")
print(ret)
运行结果:python = 998
方法2:
import re
def add(temp):
strNum = temp.group()
num = int(strNum) + 1
return str(num)
ret = re.sub(r"\d+", add, "python = 997")
print(ret)
运行结果:python = 998
8.3 split(正则, 数据)
split 根据匹配进行切割字符串,并返回一个列表
正则是描述切割的规则
返回值就是切割之后的列表
eg:切割字符串“info:xiaoZhang 33 shandong”
#coding=utf-8
import re
ret = re.split(r":| ","info:xiaoZhang 33 shandong")
print(ret)
运行结果:
['info', 'xiaoZhang', '33', 'shandong']
9. 贪婪模式与非贪婪模式
Python里数量词默认是贪婪的,总是尝试匹配尽可能多的字符;
在满足整体匹配的情况下 贪婪会尽可能的多匹配 非贪婪会尽可能少的匹配
如果想要让python使用非贪婪模式 在量词"*","?","+","{m,n}"等之后加上?
贪婪尽可能多,非贪婪尽可能少。 贪婪和非贪婪必须有一个前提就是满足整体匹配结果。
eg:
>>> s="This is a number 234-235-22-423"
>>> r=re.match(".+(\d+-\d+-\d+-\d+)",s)
>>> r.group(1)
'4-235-22-423'
>>> r=re.match(".+?(\d+-\d+-\d+-\d+)",s)
>>> r.group(1)
'234-235-22-423'
>>> re.match(r"aa(\d+)","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)","aa2343ddd").group(1)
'2'
>>> re.match(r"aa(\d+)ddd","aa2343ddd").group(1)
'2343'
>>> re.match(r"aa(\d+?)ddd","aa2343ddd").group(1)
'2343'
In [36]: res = re.search("^(\w+)_(\w+?)$","hello_world")
In [37]: res.group()
Out[37]: 'hello_world'
In [38]: res.group(1)
Out[38]: 'hello'
In [39]: res.group(2)
Out[39]: 'world'
10. Python中字符串前面加上 r 表示原生字符串
自动会对字符串中的\进行转义 ---- > 解决在匹配多\的情况的困扰
>>> mm = "c:\\a\\b\\c"
>>> mm
'c:\\a\\b\\c'
>>> print(mm)
c:\a\b\c
>>> re.match("c:\\\\",mm).group()
'c:\\'
>>> ret = re.match("c:\\\\",mm).group()
>>> print(ret)
c:\
>>> ret = re.match("c:\\\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a
>>> ret = re.match(r"c:\a",mm).group()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'group'
>>>
与大多数编程语言相同,正则表达式里使用"“作为转义字符,这就可能造成反斜杠困扰。
假如你需要匹配文本中的两个字符”\w",python语言层级会先尝试对\w进行转义 (比如\n\r\v\t\f\e\0等) 如果不属于ASCII码中的转义字符就会’\w’自动转义为两个反斜杠 \w。
那么 使用编程语言的正则表达式里将需要4个反斜杠"\": 对于python语言来讲会将两个连续的‘\’解释为一个
前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
Python里的原生字符串很好地解决了这个问题,有了原生字符串,再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
>>> ret = re.match(r"c:\\a",mm).group()
>>> print(ret)
c:\a