Python进阶--模块-re

Python进阶–模块-re

1. 正则表达式

正则表达式,在字符串处理业务中经常会用到。这里对正则表达式的匹配规则不再赘述,我们仅介绍Python的re模块。

2. findall

2.1 方法解析

findallre模块中常用的方法,与其他方法不同的是他的返回值是一个列表

findall(pattern, string, flags=0):
    return list()
  • findall:正则匹配模型
  • string:要匹配的字符串
  • flag:匹配模式

2.2 举个栗子

import re

s = "aAbBcCdD"
f = re.findall(r"[a-z][A-Z][a-z]", s)

print(f)

['aAb', 'cCd']

观察结果我们不难发现:并没有匹配到bBc,对其分析:

  1. 匹配时首先匹配到aAb并加入返回的列表中
  2. 继续匹配,此时指针指到字符B(接着匹配,而不重头再来),字符B不符合,不断后移。
  3. 匹配到字符串bCc

由此得出结论:

匹配成功后,再次匹配时,会从已匹配字符串的后一位开始匹配(并不重新开始)。简言之,已经匹配过的字符串不会参与到后续匹配。


2.3 匹配模式

findall方法有参数flag表示匹配模式,其含义如下:

re.A 或 re.ASCII使用ASCII字符集进行匹配(不常用)
re.I 或 re.IGNORECASE忽略大小写匹配
re.L 或 re.LOCALE使用当前预定字符类 \w \W \b \B \s \S 取决于当前区域设定(不常用)
re.U 或 re.UNICODE使用Unicode字符类 \w \W \b \B \s \S \d \D 取决于unicode定义的字符属性(不常用)
re.M 或 re.MULTILINE多行匹配,使"^","$"可以在每一行中都进行匹配
re.S 或 re.DOTALL使 “.” 可以匹配换行符"\r","\n"
re.X 或 re.VERBOSE去掉正则表达式中的所有空格符(不常用)
import re

s = """
name: danny
age: 14
"""
f = re.findall(r": (.*?).age: (.*?)$", s)
f_s = re.findall(r": (.*?).age: (.*?)\b$", s, re.S)
f_n = re.findall(r": (.*?)\nage: (.*?)\b$", s, re.S)

print("f: ",f)
print("f_s: ",f_s)
print("f_n: ",f_n)

f:  []
f_s:  [('danny', '14')]
f_n:  [('danny', '14')]

首行的danny和次行的age之间有换行符\n,正常模式下元符号.无法匹配到\n \r等。但是,使用模式re.S后,元符号.可以匹配到\n \r

f的结果为空,f_s匹配到字符串,f_n是对照组。

3.4 分组

3.4.1 简介

什么是?简单来说当我们想要从符合匹配规则的字符串中提取一段或多段字符串时,这一段段字符串就是一个个组。例如从aAbBcC中使用r"[a-z][A-Z]"取出aAbBcC ,这时我们就说,结果有三个组。

3.4.2 对比

设计对照组如下:

string = "a1b2c3d4"
no_group = r"\w\d"
has_group = r"(\w)\d"
mul_group = r"(\w)(\d)"
nest_group = r"((\w)(\d))"

print("无分组:", re.findall(no_group, string))
print("有分组:", re.findall(has_group, string))    #将“组”内信息用圆括号包裹
print("多分组:", re.findall(mul_group, string))
print("嵌套分组:", re.findall(nest_group, string))

无分组: ['a1', 'b2', 'c3', 'd4']
有分组: ['a', 'b', 'c', 'd']
多分组: [('a', '1'), ('b', '2'), ('c', '3'), ('d', '4')]
嵌套分组: [('a1', 'a', '1'), ('b2', 'b', '2'), ('c3', 'c', '3'), ('d4', 'd', '4')]
  • 无分组时,从符合的字符串中返回匹配结果,如字符串“a1”。

  • 有分组时,仅返回组内成分(圆括号包含的就是组的范围),如字符串"a"。

  • 多个分组时,将所有组封入元祖,每个元祖代表一个匹配到的字符串的结果(如('a', '1')),再与其他结果(如('b', '2')等等)一同封入列表返回

  • 嵌套分组时由外到内,将每个组依序封入元祖。上例中依序将组((\w)(\d)),(\w),(\d)

    再次强调:匹配时先依据匹配规则找到匹配的字符串(如’a1’),再对字符串(“a1”)做分组处理,组依于匹配到的字符串而进行操作。分组其实就是说清楚,告诉机器本山人要的是匹配到的字符串的哪一部分。

3.4.3 打开分组

使用?:可以打开分组,本方法仅适用于不返回re.Match对象的方法,如findall

string = "a1b2c3d4"
no_group = r"\w\d"
has_group = r"(\w)\d"
open_group = r"(?:\w)\d"

print("无分组:", re.findall(no_group, string))
print("有分组:", re.findall(has_group, string))
print("打开分组:", re.findall(open_group, string))

无分组: ['a1', 'b2', 'c3', 'd4']
有分组: ['a', 'b', 'c', 'd']
打开分组: ['a1', 'b2', 'c3', 'd4']

3. match

3.1 方法解析

match方法用于从字符串头开始匹配符合规则的子字符串,注意是从头开始

def match(pattern, string, flags=0):
    return re.Match()
  • match方法同样接受匹配模式flag字段。

3.2 举个栗子

s = "hello world hello Python"
r = r"h\w+\s\w+"

res = re.match(r, s)     #只能匹配到 hello world,因为match方法只从字符串开头开始匹配,不匹配其他位置。
print(res.group())       

hello world
  • 从起始位置起,开始匹配,匹配到则返回Match对象,反之则返回None

4. search

4.1 方法解析

search,浏览全部字符串,匹配第一符合规则的字符串,浏览整个字符串去匹配第一个,未匹配成功返回None。

def search(pattern, string, flags=0):
    return re.Match

4.2 举个栗子

s = '''
    <li class=""><a ka="header-job" href="https://www.zhipin.com/job_detail/">职位</a></li>
    <li class=""><a ka="header_brand" href="https://www.zhipin.com/gongsi/">公司</a></li>
    <li class=""><a ka="header-job" href="https://zhiwei url/">职位</a></li>
    <li class=""><a ka="header_brand" href="https://gongsi url/">公司</a></li>
'''.strip()
r = r'.*?job" href="(.*?)/".*?brand" href="(.*?)/"'
res = re.search(r, s, re.S)
print("未分组:", res.group(0))
print("组1内容:", res.group(1))

未分组: <li class=""><a ka="header-job" href="https://zhiwei url/">职位</a></li>
        <li class=""><a ka="header_brand" href="https://gongsi url/"1内容: https://zhiwei url
  • 只匹配第一符合的字符串,所以后面的https://zhiwei url不会匹配。

5. Match对象

5.1 简介

re模块中,方法findall返回的是列表对象,可以索引取值,但方法match和search返回值是re.Match对象 。注:为了方便,我们称之为Match对象,全称为:_sre.SRE_Match

s = "hello world hello Python"
r = r"h\w+\s\w+"

res = re.match(r, s)
print(type(res))
print(dir(res))

<class '_sre.SRE_Match'>
[
    'group', 
    'groupdict', 
    'groups', 
    'lastgroup', 
    'start'
    ......
]

5.2 使用

关于**_sre.SRE_Match**对象(以下简称Match对象)的使用,如下所示:

属性和方法说 明
Pos搜索的开始位置
Endpos搜索的结束位置
String搜索的字符串
Re当前使用的正则表达式的对象
Lastindex最后匹配的组索引
Lastgroup最后匹配的组名
group(index=0)某个分组的匹配结果。如果index等于0,便是匹配整个正则表达式
groups()所有分组的匹配结果,每个分组的结果组成一个列表返回
Groupdict()返回组名作为key,每个分组的匹配结果座位value的字典
start([group])获取组的开始位置
end([group])获取组的结束位置
span([group])获取组的开始和结束位置
expand(template)使用组的匹配结果来替换模板template中的内容,并把替换后的字符串返回
1. group

group方法用于分组(圆括号中的内容)

#match.group([group1, ...])
  • 如果组中组出的参数0,表示不分组,则返回整个匹配的值。
  • 如果组中组出的参数是负数或超出组的最大长度,则给出越界错误。
  • 参数可以是两个值,返回元组,元组内包含对应“组”的字符串。
  • 未匹配到值的组结果为None。
s = '''
    <li class=""><a ka="header-job" href="https://www.zhipin.com/job_detail/">职位</a></li>
    <li class=""><a ka="header_brand" href="https://www.zhipin.com/gongsi/">公司</a></li>
'''.strip()
r = r'.*?job" href=(.*?)/".*?brand" href=(.*?)/"'

res = re.match(r, s, re.S)
print("未分组:", res.group())     #默认参数为0,即返回所匹配到的字符串,不分组
print("组1内容:", res.group(1))
print("组1,2内容:", res.group(1, 2))

未分组: <li class=""><a ka="header-job" href="https://www.zhipin.com/job_detail/">职位</a></li>
        <li class=""><a ka="header_brand" href="https://www.zhipin.com/gongsi/"1内容: "https://www.zhipin.com/job_detail
组1,2内容: ('"https://www.zhipin.com/job_detail', '"https://www.zhipin.com/gongsi')
2. groups

方法groups以元祖形式返回所有组。

s = '''
    <li class=""><a ka="header-job" href="https://www.zhipin.com/job_detail/">职位</a></li>
    <li class=""><a ka="header_brand" href="https://www.zhipin.com/gongsi/">公司</a></li>
'''.strip()
r = r'.*?job" href=(.*?)/".*?brand" href=(.*?)/"'

res = re.match(r, s, re.S)
print("所有组:", res.groups())

所有组: ('https://www.zhipin.com/job_detail', 'https://www.zhipin.com/gongsi')
3. groupdict

方法groupdict返回命名过的组,未命名的不管。

s = '''
    <li class=""><a ka="header-job" href="https://www.zhipin.com/job_detail/">职位</a></li>
    <li class=""><a ka="header_brand" href="https://www.zhipin.com/gongsi/">公司</a></li>
'''.strip()
r = r'.*?job" href="(?P<zhiwei>.*?)/".*?brand" href="(.*?)/"'  #组1命名为zhiwei返回,组2未命名不返回

res = re.match(r, s, re.S)
print("命名组:", res.groupdict())

命名组: {'zhiwei': 'https://www.zhipin.com/job_detail'}
  • 命名通过?P<name>完成
  • 只返回命名过的
4. start & end

方法start返回对应组的起始字符在初始字符串string中的位置。

方法start返回对应组的结束字符在初始字符串string中的位置。

def start(group=0):
    return start_index

def end(group=0):
    return end_index
  • group:组的编号
s = '''
    <li class=""><a ka="header-job" href="https://www.zhipin.com/job_detail/">职位</a></li>
    <li class=""><a ka="header_brand" href="https://www.zhipin.com/gongsi/">公司</a></li>
'''.strip()
r = r'.*?job" href="(?P<zhiwei>.*?)/".*?brand" href="(.*?)/"'  #组1命名为zhiwei返回,组2未命名不返回

res = re.match(r, s, re.S)
print("组1开始位置:", res.start(1))
print("组2结束位置:", res.end(2))
print("结束位字符:", s[163])1开始位置: 382结束位置: 163
结束位字符: /
  • 方法end返回的结束位字符索引值是真实索引值+1
5. span

方法span返回组的起始位置和结束位置构成的元祖,即该组的索引范围。

s = '''
    <li class=""><a ka="header-job" href="https://www.zhipin.com/job_detail/">职位</a></li>
    <li class=""><a ka="header_brand" href="https://www.zhipin.com/gongsi/">公司</a></li>
'''.strip()
r = r'.*?job" href="(?P<zhiwei>.*?)/".*?brand" href="(.*?)/"'  #组1命名为zhiwei返回,组2未命名不返回

res = re.match(r, s, re.S)
print("组1索引范围:", res.span(1))
print("索引范围对应的字符串:", eval("s[{0}:{1}]".format(*res.span(1))))  #取出该范围的字符串,等价于r[38:71]
print("组1内容:", res.group(1))1索引范围: (38, 71)
索引范围对应的字符串: https://www.zhipin.com/job_detail
组1内容: https://www.zhipin.com/job_detail
  • 方法span返回的索引范围可直接用于提取字符串,即结束位置(71)其实是末尾字符(“l”)的索引值+1。其实返回的是(res.start(1), res.end(1))
6 expand

方法expand作用:在参数字符串中,将特定内容替换为组的内容,类似于字符串格式化。

s = '''
    <li class=""><a ka="header-job" href="https://www.zhipin.com/job_detail/">职位</a></li>
    <li class=""><a ka="header_brand" href="https://www.zhipin.com/gongsi/">公司</a></li>
'''.strip()
r = r'.*?job" href="(?P<zhiwei>.*?)/".*?brand" href="(.*?)/"'  #组1命名为zhiwei返回,组2未命名不返回

res = re.match(r, s, re.S)
str_expand = r""" 
        公司:\2;                #\2 会被替换为组2内容
        公司:\g<2>			  #\g<2> 会被替换为组2内容
        职位:\g<zhiwei>          #\g<zhiwei> 会被替换为组名为 zhiwei 的组的内容
     """
print("expand替换结果:", res.expand(str_expand))

expand替换结果: 
        公司:https://www.zhipin.com/gongsi;
        公司:https://www.zhipin.com/gongsi
        职位:https://www.zhipin.com/job_detail
  • 替换标志:\组编号\g<组编号>\g<组名>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值