如何把一个字符串的特征或规则告诉给计算机,让计算机知道你要描述的东西。被称为正则。
了解正则表达式
正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。
如何把一个字符串的特征或规则告诉给计算机,让计算机知道你要描述的东西。被称为正则。
re模块操作
Python当中提供正则表达式的基本模块
模块当中提供了一些关于正则的方法
代码语言:javascript复制1、re.match(正则表达式,要匹配的字符串)
若字符串匹配正则表达式则match方法返回匹配对象,否则返回None
也可以在Match
对象上用group()
方法提取出子串来 如下
正则表达式的匹配规则
表示字符
字符 | 功能 |
---|---|
. | 匹配任意1个字符(除了n) |
[ ] | 匹配[ ]中列举的字符 |
d | 匹配数字,即0-9 |
D | 匹配非数字,即不是数字 |
s | 匹配空白,即 空格,tab键 |
S | 匹配非空白 |
w | 匹配单词字符,即a-z、A-Z、0-9、_ |
W | 匹配非单词字符 |
表示数量
字符 | 功能 |
---|---|
* | 匹配前一个字符出现0次或者无限次,即可有可无 |
| 匹配前一个字符出现1次或者无限次,即至少有1次 |
? | 匹配前一个字符出现1次或者0次,即要么有1次,要么没有 |
{m} | 匹配前一个字符出现m次 |
{m,} | 匹配前一个字符至少出现m次 |
{m,n} | 匹配前一个字符出现从m到n次 |
表示边界
字符 | 功能 |
---|---|
^ | 匹配字符串开头 |
$ | 匹配字符串结尾 |
b | 匹配一个单词的边界 |
B | 匹配非单词边界 |
匹配分组
字符 | 功能 | ||
---|---|---|---|
匹配左右任意一个表达式 | |||
(ab) | 将括号中字符作为一个分组 | ||
num | 引用分组num匹配到的字符串 | ||
(?P<name>) | 分组起别名 | ||
(?P=name) | 引用别名为name分组匹配到的字符串 |
更精准匹配
要做更精确地匹配,可以用[]
表示范围
比如匹配手机号 在大陆手机号的第一位都是1
而第二位貌似只能是 3,4,5,7,8
那么要做到更精准我们可以这样写
上面有/d /D 大写表示取反的作用那[]
也是可以取反的
前面加一个^就表示对括号里面的取反
小练习:匹配手机号的正则表达式
代码语言:javascript复制>>> import re
>>> re.match("^1[35678]d{9}$","18711111111")
<re.Match object; span=(0, 11), match='18711111111'>
原始字符串
这块我最开始也是比较懵的 可能有点难理解
Python中字符串前面加上 r 表示原生字符串
,
与大多数编程语言相同,正则表达式里使用""作为转义字符
,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符”“,那么使用编程语言表示的正则表达式里将需要4个反斜杠”“:前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。
像用'\\'
来匹配的处理办法看上去太丑陋了。为了简化理解和操作,Python提供了原始字符串
'\\'
在正则匹配函数中先被理解为'\'
,而'\'
用来匹配待处理字符串,则再一次被理解为用来匹配字符串。
实际案例
匹配出0-100之间的数字
代码语言:javascript复制>>> import re
>>> re.match(r"[1-9]?d?$|100$","0")
<re.Match object; span=(0, 1), match='0'>
>>> re.match(r"[1-9]?d?$|100$","100")
<re.Match object; span=(0, 3), match='100'>
>>> re.match(r"[1-9]?d?$|100$","52")
<re.Match object; span=(0, 2), match='52'>
分组提取
代码语言:javascript复制>>> result = re.match(r"<h1>(.*)</h1>","<h1>匹配分组</h1>")
>>> result.group()
'<h1>匹配分组</h1>'
>>> result.group(1)
'匹配分组'
正则表达式中出现了一个括号 所以group(1)会提取出第一个括号里的内容
代码语言:javascript复制>>> result = re.match(r"(<h1>)(.*)(</h1>)","<h1>匹配分组</h1>")
>>> result.group(1)
'<h1>'
>>> result.group(3)
'</h1>'
>>> result.group(0)
'<h1>匹配分组</h1>'
group(0) 会提取出整个内容
分组进阶提取
我们都知道html标签都是会成对出现的
那么我们应该写一个可以成对匹配的正则表达式
代码语言:javascript复制>>> s = "<html><h1>itcast</h1></html>"
>>> re.match(r"<(. )><(. )>. </2></1>",s)// 1表示第一个分组 2表示第二个分组
<re.Match object; span=(0, 28), match='<html><h1>itcast</h1></html>'>
>>> s = "<html><h1>itcast</h2></script>"
>>> re.match(r"<(. )><(. )>. </2></1>",s)
橙色框的案例 前后标签不同所以无法匹配
看起来这样做确实很不错 不过我如果有一万个分组那该怎么办
挨个数然后</10000>么 显然不可能
还有一种方法 前面匹配的表里有些写过
给分组命名
代码语言:javascript复制import re
ret = re.match(r"<(?P<name1>w*)><(?P<name2>w*)>.*</(?P=name2)></(?P=name1)>", "<html><h1>www.itcast.cn</h1></html>")
ret.group()
re模块高级用法
re.search
search方法与match方法极其类似,区别在于match()函数只检测re是不是在string的开始位置匹配,search()会扫描整个string查找匹配,match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回None。同样,search方法的返回对象同样match()返回对象的方法和属性
这种情况下match就无法匹配
re.findall
以列表形式返回全部能匹配的子串
符合匹配以后会继续往下寻找匹配的字符串
re.sub
将匹配到的数据进行替换
将标签替换为空 意思是只匹配文字
执行后效果为
re.split
根据匹配进行切割字符串,并返回一个列表
代码语言:javascript复制#split 匹配切割字符串
>>>c = "ctf:php,python,web-misc"
>>>d = re.split(r":|,|-",c)//用(: , -)为依据 分割字符串
>>>print(d)
['ctf', 'php', 'python', 'web', 'misc']
贪婪和非贪婪
Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;
非贪婪则相反,总是尝试匹配尽可能少的字符。
在”*”,”?”,” ”,”{m,n}”后面加上?,使贪婪变成非贪婪。
代码语言:javascript复制>>> 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'
正则表达式模式中使用到通配字,那它在从左到右的顺序求值时,会尽量“抓取”满足匹配最长字符串,在我们上面的例子里面,“. ”会从字符串的启始处抓取满足模式的最长字符,其中包括我们想得到的第一个整型字段的中的大部分,“d ”只需一位字符就可以匹配,所以它匹配了数字“4”,而“. ”则匹配了从字符串起始到这个第一位数字4之前的所有字符。
解决方式:非贪婪操作符“?”,这个操作符可以用在”*”,” ”,”?”的后面,要求正则匹配的越少越好。
小练习
1提取图片链接
代码语言:javascript复制e =
"""
<img dataoriginal="https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg" src="https://rpic.ucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg" style="display: inline;">
"""
f = re.search("http. ?.jpg",e)
print(f.group())
结果为
代码语言:javascript复制https://rpic.douyucdn.cn/appCovers/2016/11/13/1213973_201611131917_small.jpg
2提取网址
代码语言:javascript复制http://www.interoem.com/messageinfo.asp?id=35
正则提取后为
代码语言:javascript复制http://www.interoem.com/
代码为
代码语言:javascript复制g = "http://www.interoem.com/messageinfo.asp?id=35"
h = re.sub("(http://. ?/).*",lambda x:x.group(1),g)
print(h)