Python学习17-正则表达式

一、简述

正则表达式:对【指定的字符串】与【模式】之间进行模式匹配,可以获得模式匹配的结果。

模式:可以是普通字符串,也可以是含有特殊意义的字符(正则表达式)

python中re模块是来支持正则表达式

re.search(模式,待搜索的字符串),返回的是匹配对象
匹配对象下的group方法可以返回匹配的内容
使用方法如下:

import re
r = re.search("abc","abccd")
if r:
    print(r.group())
else:
    print("没有匹配")

输出结果为:

abc

如果不使用group方法,则输出如下:

import re
r = re.search("abc","abccd")
r1 = re.search("abc","edf")
print(r)
print(r1)

输出:

<_sre.SRE_Match object; span=(0, 3), match='abc'>
None

二、正则表达式的特殊字符

1)字符相关

在这里插入图片描述

(1).:默认模式下,匹配除了\n以外的单个字符,如果修改了S—re.DOTALL 模式,匹配的是所有的单个字符
使用方法如下:

import re
r = re.search("a.c","abccd")
r1 = re.search("a.c","a\ncd")
r2 = re.search("a.c","a\ncd",re.DOTALL)
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)

输出:

abc
不匹配
a
c

匹配到a\nc时,会把\n当做换行符进行输出。
(2)[]:匹配中括号内 任意一个字符,[]可以是多个单个字符,也可以是区间(从哪到哪)
-代表区间,\表示转义,也可以放在两端
使用方法如下:

import re
r = re.search("a[bef]c","abccd")
r1 = re.search("a[b-f]c","adcd")
r2 = re.search("a[-df]c","a-cd")
r3 = re.search("a[d\-c]c","a-cd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)
R(r3)

输出:

abc
adc
a-c
a-c

(3) [^] (重要) 表示[]内容取反,注意^必须放在第一个位置
使用方法如下:

import re
r = re.search("a[^bef]c","abccd")
r1 = re.search("a[^b]c","adcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

不匹配
adc

(4)\d (重要) :代表的数字(不限于0-9,还有有特殊的字符)
如果是str类型,匹配Unicode十进制数字,这包括但不限于0 ~ 9,例如0,٧等字符,也能够匹配成功。如果是bytes类型,匹配[0-9]。
使用方法如下:

import re
r = re.search("a\dc","a6ccd")
r1 = re.search("a\dc","a٧cd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出为:

a6c
a٧c

(5)\D:代表\d的取反:匹配非Unicode数字字符
使用方法如下:

import re
r = re.search("a\Dc","a.ccd")
r1 = re.search("a\Dc","a٧cd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

a.c
不匹配

(6)\s:如果是str类型,匹配Unicode空白符,这包括但不限于[空格\t\v\r\n\f]。如果是bytes类型,匹配[空格\t\v\r\n\f]
使用方法如下:

import re
r = re.search("a\sc","a\tccd")
r1 = re.search("a\sc","abcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

a	c
不匹配

(7)\S:匹配非Unicode空白字符,\s的取反匹配
使用方法如下:

import re
r = re.search("a\Sc","a\tccd")
r1 = re.search("a\Sc","abcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

不匹配
abc

(8)\w:如果是str类型,匹配Unicode单词字符,这包括但不限于[a-zA-Z0-9_]。如果是bytes类型,则匹配[a-zA-Z0-9_]。
使用方法如下:

import re
r = re.search("a\wc","a\tccd")
r1 = re.search("a\wc","aZcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出结果为:

不匹配
aZc

(9)\W :匹配非Unicode单词字符,\w的取反匹配。
使用方法如下:

import re
r = re.search("a\Wc","a\tccd")
r1 = re.search("a\Wc","a?cd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

a	c
a?c

2)次数相关:注意必须前面有字符才有作用

跟次数相关的特殊字符除了{m}以外都是贪婪匹配
在这里插入图片描述
(1)*:匹配前面的字符0次或多次,
使用方法如下:

import re
r = re.search("ab*","acd")
r1 = re.search("ab*","abcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出为:

a
ab

(2)+:匹配一次或多次
匹配模式是贪婪匹配:即匹配最多数量的字符

import re
r = re.search("ab+","acd")
r1 = re.search("ab+","abcd")
r2 = re.search("ab+","abbbbbbbc")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)

输出:

不匹配
ab
abbbbbbb

(3)?:匹配0次或1次

import re
r = re.search("ab?","acd")
r1 = re.search("ab?","abcd")
r2 = re.search("ab?","abbbbbbbc")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)

输出:

a
ab
ab

(4){m}:匹配前面的字符m次

import re
r = re.search("ab{1}","acd")
r1 = re.search("ab{1}","abbbcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

不匹配
ab

(5){m,}:匹配前面的字符至少m次,贪婪匹配

import re
r = re.search("ab{1,}","acd")
r1 = re.search("ab{1,}","abbbcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

import re
r = re.search("ab{1,}","acd")
r1 = re.search("ab{1,}","abbbcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

(6){,n}:匹配前面的字符至多n次,可以是0次

import re
r = re.search("ab{,5}","acd")
r1 = re.search("ab{,5}","abbbcd")
r2 = re.search("ab{,5}","abbbbbbbc")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)

输出:

a
abbb
abbbbb

(7){m,n}:匹配前面字符m到n次,既包含m次,也包含n次,且是贪婪匹配

import re
r = re.search("ab{2,5}","abbcd")
r1 = re.search("ab{2,5}","abbbbbbcd")
r2 = re.search("ab{2,5}","abbbbc")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)

输出:

abb
abbbbb
abbbb

(8)X?:将以上的特殊字符(除{m}以外),变成非贪婪模式

import re
r = re.search("ab*?","abbcd")
r1 = re.search("ab{2,5}?","abbbbbbcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

a
abb

3)边界相关

在这里插入图片描述
(1)^:匹配字符串的开头。在多行模式下,可以匹配每一行的开头。
默认单行匹配,需要加入 re.MULTILINE

import re
r = re.search("^张\w{1,2}","张三\n张五")
r1 = re.search("^张\w{1,2}","三\n张五")
r2 =re.search("^张\w{1,2}","三\n张五",re.MULTILINE)
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)

输出:

张三
不匹配
张五

(2)$:匹配字符串的结尾。在多行模式下,可以匹配每一行的末尾

import re
r = re.search("\w{1,2}五$","张三\n张五")
r1 = re.search("\w{1,2}五$","王五\n张五")
r2 =re.search("\w{1,2}五$","王五\n张五",re.MULTILINE)
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)

输出:

张五
张五
王五

(3)\A:仅匹配字符串的开头,只支持单行模式
\Z:仅匹配字符串的末尾,只支持单行模式

(4)\b:匹配单词的边界。单词可以含有Unicode字符、数字与下划线组成(\w+匹配的内容)。\b匹配的是空串,该空串可以出现在\w(\W)与\W(\w)之间、字符串开头与\w之间或\w与字符串结尾之间。
之间:字符和字符之间,字符和“墙”(墙是非unicode字符)
可以理解为在单词的边界进行匹配

import re
r = re.search(r"\bcd","cd")
r1 = re.search(r"\bcd","cd1")
r2 = re.search(r"\bcd","1cd")
r3 = re.search(r"\bcd","1cd1")

def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)
R(r3)

输出:

cd
cd
不匹配
不匹配

(5)\B:匹配单词的非边界。\B匹配的是空串,该空串必须出现在两个\w之间。\B是\b的取反匹配。
可以理解为在单词的非边界进行匹配

r = re.search(r"\Bcd","cd")
r1 = re.search(r"\Bcd","cd1")
r2 = re.search(r"\Bcd","1cd")
r3 = re.search(r"\Bcd","1cd1")

def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)
R(r2)
R(r3)

输出:

不匹配
不匹配
cd
cd

4)组相关

在这里插入图片描述
(1)():对()内的字符进行分组。分组后,该组匹配的内容可以单独提取,同时,也可以在模式字符串后面使用\number进行引用。

import re
r = re.search("ab(cd)+","abcdcdcdcdcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)

输出:

abcdcdcdcdcd

简单应用一:匹配加粗字体

r = re.search(r"<b>(.*)</b>", "<b>一些加粗的内容</b>")
if r:
    print(r.group())
    print(r.group(1)) # 索引代表括号,从1开始
else:
    print("不匹配")

简单应用二:匹配电话号

r = re.search(r"([0-9]{3,4})-([0-9]{7,8})", "010-12345678")
if r:
    print(r.group())
    print(r.group(1))
    print(r.group(2))
else:
    print("不匹配")

(2)\number:number用来指定组序号,序号从1开始。用来匹配number对应的分组内容

import re
r = re.search(r"<([a-zA-Z]+)>(.*)</\1>", "<title>一些加粗的内容</title></b>")
if r:
    print(r.group())
    print(r.group(1)) # 索引代表括号,从1开始
    print(r.group(2)) # 索引代表括号,从1开始
else:
    print("不匹配")

输出:

<title>一些加粗的内容</title>
title
一些加粗的内容

(3)(?:正则表达式):削弱()功能,使得()功能只有括号内的内容整体操作

import re
r = re.search(r"(?:[0-9]{3,4})-(?:[0-9]{7,8})", "010-12345678")
if r:
    print(r.group())
    #print(r.group(1))  单独对()内的内容操作时会报错
    #print(r.group(2))
else:
    print("不匹配")

输出:

010-12345678

(4)(?P<name>表达式):对()内的字符进行分组,组名为name,多个组之间的名称不能重复。分组后,该组匹配的内容可以单独提取,同时,也可对()内的字符进行分组,组名为name,多个组之间的名称不能重复。分组后,该组匹配的内容可以单独提取,同时,也可以在模式字符串后面使用(?P=name)或\number进行引用。对比之前()进行的序号分组,此种方式可以称为命名分组。不过,命名分组依然也可以使用序号(\number)进行引用。

import re
r = re.search(r"<(?P<tag>[a-zA-Z]+)>(.*)</(?P=tag)>","<title>一些加粗的内容</title></b>")
if r:
    print(r.group())
    print(r.group(1))
    print(r.group(2))
else:
    print("不匹配")

输出:

<title>一些加粗的内容</title>
title
一些加粗的内容

(5)|:用来连接两个并列的模式字符串,匹配其中的一个即可。
|级别很低,大范围的划取

import re
r = re.search("abc|def","def")
r1 = re.search("abc(d|e)f","abcef")
def R(r):
    if r:
        print(r.group())
    else:
        print("不匹配")
R(r)
R(r1)

输出:

def
abcef

5)控制标记

re.DOTALL----支持所有字符
re.MULTILINE----支持多行
re.IGNORECASE—忽略大小写

三、re模块的其他函数

(1)compile: 产生正则表达式对象
第一个参数:正则表达式,
第二参数:控制标记
返回值:正则表达式对象
re下的方法跟正则表达式对象下的方法几乎一样,功能有重叠,当有重复或者循环使用的时候,需要使用正则表达式对象,正则表达式只需要写一次。

import re
reobj = re.compile("abc+")
r = reobj.search("abccd")
if r:
    print(r.group())
else:
    print("没匹配")

输出:

abcc

(2)match: 跟search一样,但是只能从头部进行查找,只能返回一个匹配内容

import re
r=re.match("abc","xabc")
r1 =re.match("abc","abcd")
def R(r):
    if r:
        print(r.group())
    else:
        print("没匹配")

R(r)
R(r1)

输出:

没匹配
abc

(3)findall 返回所有匹配内容,返回到一个列表中
会取出括号内的内容

import re
r = re.findall("[0-9]","abc6sq62")
print(r)

输出:

['6', '6', '2']
import re
c ="""
<div>我是一个兵1</div>
<div>我是一个兵2</div>
<div>我是一个兵3</div>
<div>我是一个兵4</div>
"""
li = re.findall("<div>.*</div>",c)
print(li)
li1 =re.findall("<(div)>(.*)<(/div)>",c)
print(li1)
li2 = re.findall("<div>(.*)</div>",c)
print(li2)

输出:

['<div>我是一个兵1</div>', '<div>我是一个兵2</div>', '<div>我是一个兵3</div>', '<div>我是一个兵4</div>']
[('div', '我是一个兵1', '/div'), ('div', '我是一个兵2', '/div'), ('div', '我是一个兵3', '/div'), ('div', '我是一个兵4', '/div')]
['我是一个兵1', '我是一个兵2', '我是一个兵3', '我是一个兵4']

(4)finditer()功能跟findall功能类似,返回一个迭代器

import re
c ="""
<div>我是一个兵1</div>
<div>我是一个兵2</div>
<div>我是一个兵3</div>
<div>我是一个兵4</div>
"""
li = re.finditer("<div>.*</div>",c)
print(li)
li1 =re.finditer("<(div)>(.*)<(/div)>",c)
print(li1)
li2 = re.finditer("<div>(.*)</div>",c)
print(li2)
for i in li1:
    print(i.group())

输出:

<callable_iterator object at 0x000002A3A5F1B588>
<callable_iterator object at 0x000002A3A5F22F98>
<callable_iterator object at 0x000002A3A5F09CF8>
<div>我是一个兵1</div>
<div>我是一个兵2</div>
<div>我是一个兵3</div>
<div>我是一个兵4</div>

(5)split():分隔,与字符串中的spilt方法类似

import re
s ="a bc de   f"
print(s.split(" "))
print(re.split(" +",s))

输出:

['a', 'bc', 'de', '', '', 'f']
['a', 'bc', 'de', 'f']

(6)sub() 替换,跟replace很像

import re
s ="a bc de   f"
print(re.sub(" +","-",s))

输出:

a-bc-de-f

四、正则表达式对象

正则表达式如果匹配不成功,返回None,如果成功之后,会返回一个正则表达式对象
(1)string: 待匹配的文本
(2)re:正则表达式
(3)pos,endpos:字符串搜索的开始位置、结束位置的下一个位置
(4)group:返回匹配的字符串
(5)groups:返回一个元组,返回所有括号中的匹配结果
(6)start():匹配字符串在原始字符串中的起始位置
(7)end():匹配字符串在原始字符串中的终止位置,end+1
(8)span():返回start()和end()的元组

import re
m=re.search(r"(a+)-(b+)","1aaa-bbbbbb")
if m:
    print("string====》{}".format(m.string))
    print("re====》{}".format(m.re))
    print("pos====》{}".format(m.pos))
    print("endpos====》{}".format(m.endpos))
    print("group()====》{}".format(m.group()))
    print("group(1)====》{}".format(m.group(1)))
    print("groups()====》{}".format(m.groups()))
    print("start()====》{}".format(m.start()))
    print("end()====》{}".format(m.end()))
    print("span====》{}".format(m.span()))

输出:

string====1aaa-bbbbbb
re====》re.compile('(a+)-(b+)')
pos====0
endpos====11
group()====》aaa-bbbbbb
group(1)====》aaa
groups()====('aaa', 'bbbbbb')
start()====1
end()====11
span====(1, 11)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值