Python正则表达式

2022-06-09 14:13:23 浏览数 (1)

如何把一个字符串的特征或规则告诉给计算机,让计算机知道你要描述的东西。被称为正则。

了解正则表达式

正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些匹配某个模式的文本。

如何把一个字符串的特征或规则告诉给计算机,让计算机知道你要描述的东西。被称为正则。

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)

0 人点赞