ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python之正则表达式

2021-09-23 10:04:53  阅读:103  来源: 互联网

标签:匹配 re Python print 正则表达式 正则 result 字符串


 

正则表达式的定义:

        正则表达式是对字符串(包括普通字符(例如,a到z之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式, 就是用事先定义好的一些特定字符及这些字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。 正则表达式是一种文本模式,模式描述在搜索文本时要匹配的一个或多个字符串。

正则表达式的作用和特点:

给定一个正则表达式和另一个字符串,可达到以下目的:

1.给定的字符串是否符合正则表达式的过滤逻辑(称作:匹配)。

2.可以通过正则表达式,从字符串中获取我们想要的特定部分。

正则表达式的特点是:

1.灵活性,逻辑性和功能性很强。

2.可以迅速的用极简单的方式达到字符串的复杂控制。

3.对于刚接触的人来说,比较晦涩难懂。

使用场景:

如何判断一个字符串是手机号呢?

判断邮箱为163或者126的所有邮件地址。

或者是,假设我现在在写一个爬虫程序(虽然现在我还没有学哈哈),我得到了一个网页的HTML源码。其中有一段<html><body><h1>hello world<h1></body></html>,此时我想要将其中的内容“hello world”提取出来,但这时只会用字符串处理

s = "<html> <body> <h1>hello world<h1> </body> </html>"

start_index = s.find('<h1>')

正则符号与预定义:

###正则符号(量词)

. #用于匹配除换行符(\n)之外的所有字符

^ #用于匹配字符串的开始,即行首

$ #用于匹配字符串的末尾(末尾如果有换行符\n,就匹配\n前面的那个字符),即行尾

* #用于将前面的模式匹配0次或多次(贪婪模式,即尽可能多的匹配) >=0

+ #用于将前面的模式匹配1次或多次(贪婪模式) >=1

? #用于将前面的模式匹配0次或1次(贪婪模式) 0,1

*?,+?,?? #即上面三种特殊字符的非贪婪模式(尽可能少的匹配)

{m} #用于验证将前面的匹配m次

{m.} #用于验证将前面的匹配m次或多次(>=m)

{m,n} #用于将前面的模式匹配m次到n次(贪婪模式),即最小匹配m次,最多匹配n次

{m,n}? #即上面{m,n}的非贪婪版本

[] #用于标示一组字符,如果^是第一个字符,则标示的是一个补集。比如[0-9]表示所有的数字,[^0-9]表示除了数字外的字符

| #比如A|B,用于匹配A或B

(...) #用于匹配括号中的模式,可以在字符串中检索或匹配我们所需要的内容。

注意:

Python里的数量词默认是贪婪的(在少数语言里可能默认为非贪婪),总是尝试匹配更多的字符非贪婪是尽可能匹配更少的字符。将贪婪模式变为非贪婪模式,*?,+?,.?,??

###正则预定义

\A:表示从字符串的开始处进行匹配

\Z:表示从字符串的结束处匹配,如果存在换行,只匹配到换行前的结束字符串

\b:匹配一个单词边界,也就是指单词和空格间的位置。例如,’py\‘ 可以匹配”python“中的'py',但是不能匹配”openpyxl“ 中的'py'

\B:匹配非单词边界(即单词内部的字母)。'py\b'可以匹配"openpyxl"中的'py',但不能匹配"python"中的'py'

\d:匹配任意的数字,等价于 [0~9]

\D:匹配任意非数字字符,等价于 [^\d]

\s:匹配任意空白字符,等价于 [ \t \n \f \r]

\S:匹配任意非空白字符,等价于 [^\s]

\w:匹配任意字母数字及下划线,等价于 [a-z A-Z 0-9]

\W:匹配任意非字母数字及下划线,等价于 [^\w]

\\:匹配原义的反斜杠\

Python里的re模块(正则相关)

模块函数:

match:  仅从头匹配,可以拿一个正则模块同字符串头部进行匹配;匹配成功返回match对象否则返回值为空

search:匹配整个字符串,匹配成功则返回,与match一样都只能匹配到一个符合正则的字符串。

findall:搜索整个字符串,找到所有的符合正则式的字符串,以列表形式返回。

sub:遍历整个字符串,将符合正则式的字符串替换为新的字符串。

split:在字符串中如果搜索到,就会分割,将分割出的内容保留在列表中。

##应用分析A1

import re

msg = '玛尔扎哈赛恩德莱厄斯'

pattern = re.compile('玛尔扎哈')
print(pattern)
result = pattern.match(msg)  # 没有匹配到时,值为空
print(result)

输出:

re.compile('玛尔扎哈')
<re.Match object; span=(0, 4), match='玛尔扎哈'>

上面代码中使用了re模块里的compile来创建正则式,再通过其调用match来实现正则匹配。

##应用分析A2

import re
s = '泰达米尔卡特琳娜德莱文'

result = re.match('泰达米尔', s)  # 第一个参数为为正则式,第二个参数为字符串
print(result)  # match 头部匹配

###使用正则re模块的方法:search
result = re.search('卡特', s)  # 第一个参数为为正则式,第二个参数为字符串
print(result)  # search  查找匹配,找到一个后返回
print(result.span())  # 返回匹配到的字符串位置

print(result.group())  # 提取到匹配的内容

输出:

<re.Match object; span=(0, 4), match='泰达米尔'>
<re.Match object; span=(4, 6), match='卡特'>
(4, 6)
卡特

可在match方法里直接写入正则式,再写入待匹配的字符串,就可直接进行匹配啦。而且从输出结果可以看到,match仅仅是从头匹配,而search是匹配整个字符串

span()可用来返回匹配到字符串的位置,group()可返回匹配到的字符串位置。

使用量词的正则匹配:

其实,在我们实际项目的应用中,我们大多面对的是复杂字符串,而且要从中提取到符合特定逻辑的内容是比较复杂的,此时我们就可以真正的对正则的量词和预定义的灵活使用,解决这些难点。

###应用分析B1 (findall)

# 复杂字符串序列
msg = 'a2bc2d98s iui1200'

result = re.match('[a-z][0-9][a-z]', msg)
print(result.group())

result = re.findall('[a-z][0-9][a-z]', msg)  # findall 找到所有匹配的字符
print(result)  # 以列表形式返回

输出:

a2b
['a2b', 'c2d']

可见,findall匹配到所有符合的字符串后以列表形式返回;在正则式里[ ]里可表示范围的字符。

###应用分析B2 (正则量词练习)

msg = 'a7aa88aa7878aa78787878a'

result = re.findall('[a-z][0-9]+[a-z]', msg)
print(result)

##qq 号码验证  5~11  纯数字,没有字母 开头不为0
qq = '25420745800'
result = re.match('[1-9][0-9]{4,10}$', qq)  # 使用$来指明尾部
print(result)

##验证用户名  用户名可以是字母或者数字,不能是数字开头,用户名长度必须6位以上[0-9a-zA-Z]

n = 'jj001admin'
result = re.match('[a-zA-Z][0-9a-zA-Z]{5,}$', n)  # 由于验证的是一个整体单位
print(result)

msg = 'aa.py as.txt jkl.py sd.png km.py'
result = re.findall(r'\w+.py\b', msg)
print(result)

输出:

['a7a', 'a88a', 'a7878a', 'a78787878a']
<re.Match object; span=(0, 11), match='25420745800'>
<re.Match object; span=(0, 10), match='jj001admin'>
['aa.py', 'jkl.py', 'km.py']

以上就是正则符号的混合应用了,大家可以仔细看一下代码。其中最后一个输出,其正则格式使用了正则里的预定义,可以更加简化代码

###应用分析B3 ((),{},[]三者的用法)

# 匹配数字 0-100 之间
n = '100'

result = re.match(r'[1-9]?\d?$|100$', n)
print(result)

# 小括号里字符串(或者时)可作整体,而方括号里(或者时)作为单个字符
# 验证邮箱 163 126 qq
email = '321456987@qq.com'
result = re.match('\w{5,20}@(qq|126|163)\.(com|cn)$', email)
print(result)

##不是以4,7结尾的手机号码(11位)
phone = '12345678910'
result = re.match('1\d{9}[0-35-689]', phone)
print(result)

输出:

<re.Match object; span=(0, 3), match='100'>
<re.Match object; span=(0, 16), match='321456987@qq.com'>
<re.Match object; span=(0, 11), match='12345678910'>

注意。经match匹配出的结果均为match对象形式[]一般表示范围,{}表示字符出现频次,()表示分组

###应用分析B4 (分组)

# 分组 (爬虫相关)
phone = '010-12345678'
result = re.match('(\d{3}|\d{4})-(\d{8}$)', phone)
print(result)

# 分别提取
print(result.group(1))  # 输出第一组
print(result.group(2))  # 输出第二组
print(result.group())  # 输出全部

输出:

010
12345678
010-12345678

()可以以分组的形式输出匹配到的字符串,借助group()可实现对分组的提取

###应用分析B5 (两种正则式引用方法)

第一种:

msg1 = '<h1>hello</h1>'

#  \1是引用第一组的内容;number的方式
result = re.match(r'<([0-9a-zA-Z]+)>(.+)</\1>$', msg1)
print(result)
print(result.group(1))
print(result.group())

输出:

<re.Match object; span=(0, 14), match='<h1>hello</h1>'>
h1
<h1>hello</h1>

正则表达式里的引用:在写正则式的时候我们可以利用小括号()来进行分组,然后利用\1,\2...的方式,表示引用第一组和第二组的内容,这样可以极大的简写我们的代码。

第二种:

# 起名的方式  使用 ?P 对标签起名   (?P<名字>正则)   (?P = 名字)
msg = '<html><h1>asd</h1></html>'
result = re.match(r'<(?P<name1>\w+)><(?P<name2>\w+)>(.+)</(?P=name2)></(?P=name1)>', msg)
print(result.group())
print(result)

输出:
 

<html><h1>asd</h1></html>
<re.Match object; span=(0, 25), match='<html><h1>asd</h1></html>'>

这是对正则分组的式子引用的第二种方式,以<?P<name1>>的形式给字符串起名,并以<(?P=name1)>的形式引用。

###应用分析B6 ()

def func(temp):
    num = temp.group()
    num1 = int(num) + 1
    return str(num1)
result = re.sub(r'\d+', '90', 'java:95,pathon:99')  # 替换后面字符串满足条件的内容
print(result)

result = re.sub(r'\d+', func, 'java:95,pathon:99')  # 利用函数+正则来实现对字符串内容的修改
print(result)

result = re.split('[:,]','java:95,pathon:99')  #被切除的元素就没有了
print(result)

输出:

java:90,pathon:90
java:96,pathon:100
['java', '95', 'pathon', '99']

该例子用于说明sub与split方法的作用。sub(正则式,待替换的形式,旧字符串),会直接返回新的字符串split(正则式,待匹配的字符串),匹配成功后删除该字符并将整个字符串分割,以列表形式返回

标签:匹配,re,Python,print,正则表达式,正则,result,字符串
来源: https://blog.csdn.net/qq_58507432/article/details/120423745

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有