python正则表达式

1.正则表达式简介

正则表达式用于方便的检查一个字符串是否与某种模式匹配。

比如从如下文本里面获取所有职位的薪资。在这里插入图片描述
用学过的python基础对字符串进行处理,也可以用下面代码解决。

content = '''
Python3 高级开发工程师 上海互教教育科技有限公司上海-浦东新区2万/月02-18满员
测试开发工程师(C++/python) 上海墨鹍数码科技有限公司上海-浦东新区2.5万/每月02-18未满员
Python3 开发工程师 上海德拓信息技术股份有限公司上海-徐汇区1.3万/每月02-18剩余11人
测试开发工程师(Python) 赫里普(上海)信息科技有限公司上海-浦东新区1.1万/每月02-18剩余5人
Python高级开发工程师 上海行动教育科技股份有限公司上海-闵行区2.8万/月02-18剩余255人
python开发工程师 上海优似腾软件开发有限公司上海-浦东新区2.5万/每月02-18满员
'''

lines = content.splitlines()
for line in lines:
    pos2 = line.find('万/月')
    if pos2 < 0:
        pos2 = line.find('万/每月')
        if pos2 < 0: 
            continue
            
    idx = pos2-1

    while line[idx].isdigit() or line[idx]=='.':
        idx -= 1

    pos1 = idx + 1

    print(line[pos1:pos2])

但是相对于用正则表达式来说,就略有繁琐。
使用正则表达式仅需三行代码即可解决这个问题。

import re
for one in  re.findall(r'([\d.]+)万/每{0,1}月', content):
    print(one)

([\d.]+)万/每{0,1}月 ,就是正则表达式字符串,指定了 搜索子串的特征。
findall 函数在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。

2. 点

.表示要匹配除了换行符之外的任何单个字符

比如在如下文本中找出所有颜色。

content = '''苹果是绿色的
橙子是橙色的
香蕉是黄色的
乌鸦是黑色的'''

import re
a = re.compile(r'.色')#前面加r表示不进行python语法的字符串转义
for i in a.findall(content):
    print(i)

运行结果:
绿色
橙色
黄色
黑色

其中 点 代表了任意的一个字符, 注意是一个字符。

若将.色改为…色,(色前面加上两个点),运行结果为:
是绿色
是橙色
是黄色
是黑色

补充:compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
语法格式为:re.compile(pattern[, flags])
pattern : 一个字符串形式的正则表达式
flags 可选,表示匹配模式,比如忽略大小写,多行模式等

3. 星号

星号表示匹配前面的子表达式任意次,包括0次。
比如,从文本中,选择每行逗号后面的字符串内容,包括逗号本身。

content = '''苹果,是绿色的
橙子,是橙色的
香蕉,是黄色的
乌鸦,是黑色的
猴子,'''

import re
a = re.compile(r',.*')#前面加r表示不进行python语法的字符串转义
for i in a.findall(content):
    print(i)

运行结果是:
,是绿色的
,是橙色的
,是黄色的
,是黑色的

*紧跟在 . 后面,表示任意字符可以出现任意次, 所以整个表达式的意思就是在逗号后面的所有字符,包括逗号

当然,*前面可以是任意字符,可以匹配任意字符任意多次。
如下所示:

content = '''苹果,是绿色的
橙子,是橙色色色的
香蕉,是黄色的
乌鸦,是黑色的
猴子,'''

import re
a = re.compile(r'橙色*')#前面加r表示不进行python语法的字符串转义
for i in a.findall(content):
    print(i)

该段代码的运行结果是:

橙色色色

第一个结果匹配的是橙子的橙,这里匹配了零次色
第二个结果匹配的是橙色色色,这里匹配了三次色

4. 加号

在正则表达式中,加号表示匹配前面的子表达式一次或多次,不包括0次。
比如选择每行逗号后面的字符串内容,包括逗号本身,如果逗号后面没有内容,则不选择。

content = '''苹果,是绿色的
橙子,是橙色的
香蕉,是黄色的
乌鸦,是黑色的
猴子,'''

import re
a = re.compile(r',.+')#前面加r表示不进行python语法的字符串转义
for i in a.findall(content):
    print(i)

运行结果是:
,是绿色的
,是橙色的
,是黄色的
,是黑色的

最后一行逗号后面没有内容,没有进行选择。

5. 问号

在正则表达式中,? 表示匹配前面的子表达式0次或1次。
如从文本中,选择每行逗号后面的1个字符,也包括逗号本身。

content = '''苹果,是绿色的
橙子,是橙色的
香蕉,是黄色的
乌鸦,是黑色的
猴子,'''

import re
a = re.compile(r',.?')#前面加r表示不进行python语法的字符串转义
for i in a.findall(content):
    print(i)

输出结果是:
,是
,是
,是
,是

前四行中,问号表示匹配一次,最后一行,问号表示匹配零次

6. 花括号

在正则表达式中,花括号表示前面的字符匹配指定的次数 。

content = '''苹果,是绿色色色的
橙子,是橙色的
'''

import re
a = re.compile(r'色{3,4}')#前面加r表示不进行python语法的字符串转义
for i in a.findall(content):
    print(i)

运行结果是:色色色

表达式色{3} 就表示匹配连续的色字 3次
表达式色{3,4} 就表示匹配连续的色字至少3次,至多 4 次

7. 贪婪模式和非贪婪模式

贪婪模式和贪婪模式
如果要提取如下字符串中的HTML标签,

source = '<html><head><title>Title</title>'

希望得到如下的列表:

['<html>', '<head>', '<title>', '</title>']

我们可以使用正则表达式<.*>
代码如下:

source = '<html><head><title>Title</title>'
import re
a = re.compile(r'<.*>')
print(a.findall(source))

但是运行之后得到的结果是:

['<html><head><title>Title</title>']

并不是我们想要的结果。
这是因为在正则表达式中,星号、加号和问号都是贪婪的,他们在使用时会尽可能多的匹配内容,上面代码中的星号一直匹配到了字符串的最后。
解决这个问题需要改为非贪婪模式,也就是在星号后面加上 ? ,变成 <.*?>
代码改为:

source = '<html><head><title>Title</title>'
import re
a = re.compile(r'<.*?>')
print(a.findall(source))

这样就可以得到我们需要的结果。

8. 对元字符的转义

如果我们要搜索的内容本身就包含元字符,就可以使用反斜杠进行转义。
在下面的文本中搜索所有点前面的字符串时,也包含点本身,正则表达式不能写成 .*.

苹果.是绿色的
橙子.是橙色的
香蕉.是黄色的

因为点是一个元字符,直接出现在正则表达式中,表示匹配任意的单个字符,不能表示 . 这个字符本身的意思了。

这时可以使用反斜杠进行转义,将表达式写为 .*.
代码如下:

content = '''苹果.是绿色的
橙子.是橙色的
香蕉.是黄色的'''

import re
a = re.compile(r'.*\.')#前面加r表示不进行python语法的字符串转义
for one in  a.findall(content):
    print(one)

运行结果为:
苹果.
橙子.
香蕉.

9. 方括号

正则表达式中方括号表示要匹配指定的几个字符之一 。

比如:
[abc] 可以匹配 a, b, 或者 c 里面的任意一个字符,等价于 [a-c] 。
[a-c] 中间的 - 表示一个范围从a 到 c。
[a-z]可以匹配所有的小写字母

一些元字符在方括号内就变得和普通字符一样了。
比如:
[akm.] 匹配 a k m . 里面任意一个字符,其中.在括号里面不在表示匹配任意字符,而是表示匹配 . 这个字符

如果在方括号中使用 ^ , 表示非方括号里面的字符集合。
比如:\d 匹配0-9之间任意一个数字字符,[^\d] 表示选择非数字的字符。

content = 'a1b2c3d4e5'
import re
a = re.compile(r'[^\d]')#前面加r表示不进行python语法的字符串转义
for one in a.findall(content):
    print(one)

运行结果为:
a
b
c
d
e

又如提取有效的手机号。
1表示第一个数字为1,[36]表示第二个数字为3或6,\d{9}表示匹配9个0-9之间的数字

content = '''
王一,13512345678,89
徐二,1b098766456,24
李三,13212394765,33
'''
import re
a = re.compile(r'1[36]\d{9}')#前面加r表示不进行python语法的字符串转义
for one in a.findall(content):
    print(one)

运行结果为:
13512345678
13212394765

10. 单行、多行模式

^ 表示匹配文本的开头位置。
正则表达式可以设定单行模式和多行模式
如果是单行模式 ,表示匹配整个文本的开头位置。
如果是多行模式 ,表示匹配文本每行的开头位置。

比如提取文本中水果的编号:

content = '''001-苹果价格-60
002-橙子价格-70
003-香蕉价格-80'''

import re
p = re.compile(r'^\d+', re.M)#前面加r表示不进行python语法的字符串转义
for one in  p.findall(content):
    print(one)

运行结果为:
001
002
003

^\d+表示匹配开头位置的一个或多个数字,re.M表示多行模式,若去掉re.M则为单行模式,输出结果为001。
因为在单行模式下,^只会匹配整个文本的开头位置。

$ 表示匹配文本的结尾位置。
如果是单行模式 ,表示匹配整个文本的结尾位置。
如果是多行模式 ,表示匹配文本每行的结尾位置。

比如提取文本末尾的水果价格:

content = '''001-苹果价格-60
002-橙子价格-70
003-香蕉价格-80'''

import re
p = re.compile(r'\d+$',re.MULTILINE)#前面加r表示不进行python语法的字符串转义
for one in  p.findall(content):
    print(one)

运行结果为:
60
70
80

re.MULTILINE指明了使用多行模式,若去掉re.MULTILINE,则为单行模式,运行结果为80。因为单行模式下,$ 只会匹配整个文本的结束位置。

11. 括号

括号为正则表达式的组选择。

组就是把正则表达式匹配的内容里面其中的某些部分标记为某个组。

我们可以在正则表达式中标记多个组

为什么要有组的概念呢?因为我们往往需要提取已经匹配的内容里面的某些部分的信息。

从下面文本中,选择每行逗号前面的字符串,也包括逗号本身 。

​ 苹果,苹果是绿色的
​ 橙子,橙子是橙色的
​ 香蕉,香蕉是黄色的

就可以这样写正则表达式 ^.*,

但是,如果我们要求不要包括逗号呢?

当然不能直接这样写 ^.*

因为最后的逗号是特征所在, 如果去掉它,就没法找逗号前面的了。

但是把逗号放在正则表达式中,又会包含逗号。

解决问题的方法就是使用组选择符 :括号。

正则表达式可以写为 ^(.*),

比如:

content = '''苹果,苹果是绿色的
橙子,橙子是橙色的
香蕉,香蕉是黄色的'''

import re
p = re.compile(r'^(.*),', re.MULTILINE)#前面加r表示不进行python语法的字符串转义
for one in  p.findall(content):
    print(one)

运行结果为:
苹果
橙子
香蕉

当然,分组还可以进行多次。
比如,从下面的文本中选择姓名和手机号
张三,手机号码15945678901
李四,手机号码13945677701
王二,手机号码13845666901

可以使用正则表达式^(.+),.+(\d{11})
第一个分组表示获取逗号前面的姓名,第二个分组表示获取后十一位手机号码

12. 切割字符串

正则表达式中的split方法可以用于对字符串进行灵活的切割。
比如切割如下字符串:

names = '关羽; 张飞, 赵云,马超, 黄忠  李逵'

我们可以发现每两个名字之间,有的是分号隔开,有的是逗号隔开,有的是空格隔开, 而且分割符号周围还有不定数量的空格。
这时可以使用正则表达式[;,\s]\s*
分割符为分号、逗号、空格里面的任意一种均可。\s*表示任意数量的空格。

import re
names = '关羽; 张飞, 赵云,   马超, 黄忠  李逵'
namelist = re.split(r'[;,\s]\s*', names)#前面加r表示不进行python语法的字符串转义
print(namelist)

运行结果为:[‘关羽’, ‘张飞’, ‘赵云’, ‘马超’, ‘黄忠’, ‘李逵’]

13. 字符串替换

正则表达式中的split方法可以用于对字符串进行灵活的切割。
比如切割如下字符串:

names = '关羽; 张飞, 赵云,马超, 黄忠  李逵'

我们可以发现每两个名字之间,有的是分号隔开,有的是逗号隔开,有的是空格隔开, 而且分割符号周围还有不定数量的空格。
这时可以使用正则表达式[;,\s]\s*
分割符为分号、逗号、空格里面的任意一种均可。\s*表示任意数量的空格。

import re
names = '关羽; 张飞, 赵云,   马超, 黄忠  李逵'
namelist = re.split(r'[;,\s]\s*', names)#前面加r表示不进行python语法的字符串转义
print(namelist)

运行结果为:[‘关羽’, ‘张飞’, ‘赵云’, ‘马超’, ‘黄忠’, ‘李逵’]

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值