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