正则表达式

findall 函数返回所有匹配的子串,放在一个列表中。

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满员
'''

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

元字符 

. * + ? \ [ ] ^ $ { } | ( )

点-匹配所有字符

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

content1 = '''
    小狗是小的
    大狗是大的
    黄狗是黄的
    绿狗是绿的
'''
de = re.findall(r'.的',content1)
for i in de:
    print(i)

 

 星号-重复匹配任意次

* 表示匹配前面的子表达式任意次,包括0次。

content2 = '''
    水啊,是冰凉的
    火啊,是滚烫的
    宇轩,不是我的
    坤坤,是鸡叫的
'''
tt = re.findall(r',.*',content2)
for i in tt:
    print(i)

加号-重复匹配多次 

+ 表示匹配前面的子表达式一次或多次,不包括0次。

content2 = '''
    水啊,是冰凉的
    火啊,是滚烫的
    宇轩,不是我的
    坤坤,
'''
tt = re.findall(r',.+',content2)
for i in tt:
    print(i)

问号-匹配0-1次

? 表示匹配前面的子表达式0次或1次。

content2 = '''
    水啊,寄冰凉的
    火啊,你滚烫的
    宇轩,太是我的
    坤坤,美
'''
tt = re.findall(r',.?',content2)
for i in tt:
    print(i)

花括号-匹配指定次数

 花括号表示 前面的字符匹配 指定的次数 。

content2 = '''
    水啊,寄冰凉的
    火啊,你滚烫的
    宇轩,太是我的
    坤坤,美
'''
tt = re.findall(r',.{1}',content2)
for i in tt:
    print(i)

贪婪模式和非贪婪模式 

p1 = re.compile(r'<.*>')
p2 = re.compile(r'<.*?>')
print(p1.findall(source))
print(p2.findall(source))

造成结果存在差异的原因是p1使用了贪婪模式,即<.*>他会尽可能多地去把 匹配内容的情况。

而非贪婪模式则是点到为止。

对元字符的转义

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

import re
p1 = re.compile(r'.*\.')
p2 = re.compile(r'.*.')
print(type(p1))
for one in  p1.findall(content):
    print(one)
for one in  p2.findall(content):
    print(one)

 匹配某种字符类型

\d 匹配0-9之间任意一个数字字符,等价于表达式 [0-9]

\D 匹配任意一个不是0-9之间的数字字符,等价于表达式 [^0-9]

\s 匹配任意一个空白字符,包括 空格、tab、换行符等,等价于表达式 [\t\n\r\f\v]

\S 匹配任意一个非空白字符,等价于表达式 [^ \t\n\r\f\v]

\w 匹配任意一个文字字符,包括大小写字母、数字、下划线,等价于表达式 [a-zA-Z0-9_]

缺省情况也包括 Unicode文字字符,如果指定 ASCII 码标记,则只包括ASCII字母

\W 匹配任意一个非文字字符,等价于表达式 [^a-zA-Z0-9_]

方括号-匹配几个字符之一

方括号表示要匹配 指定的几个字符之一 。

比如

[abc] 可以匹配 a, b, 或者 c 里面的任意一个字符。等价于 [a-c] 。

[a-c] 中间的 - 表示一个范围从a 到 c。

如果你想匹配所有的小写字母,可以使用 [a-z]

一些 元字符 在 方括号内 失去了魔法, 变得和普通字符一样了。

比如

[akm.] 匹配 a k m . 里面任意一个字符

这里 . 在括号里面不在表示 匹配任意字符了,而就是表示匹配 . 这个 字符


如果在方括号中使用 ^ , 表示  方括号里面的字符集合。

content = 'a1b2c3d4e5'
p = re.compile(r'[^\d]' )
for one in  p.findall(content):
    print(one)

起始、结尾位置 和 单行、多行模式

^ 表示匹配文本的 开头 位置。

正则表达式可以设定 单行模式 和 多行模式

如果是 单行模式 ,表示匹配 整个文本 的开头位置。

如果是 多行模式 ,表示匹配 文本每行 的开头位置。

多行模式

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

p = re.compile(r'^\d+', re.M)
for one in  p.findall(content):
    print(one)

 

如果,去掉 compile 的第二个参数 re.M, 运行结果如下

$ 表示匹配文本的 结尾 位置。

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

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

p = re.compile(r'\d+$',re.M)
for one in  p.findall(content):
    print(one)

 

竖线-匹配其中之一 

特别要注意的是, 竖线在正则表达式的优先级是最低的, 这就意味着,竖线隔开的部分是一个整体

比如 绿色|橙 表示 要匹配是 绿色 或者  ,

而不是 绿色 或者 绿橙

content = '''苹果,是红色的
菠萝,是黄色的
小草,是绿色的'''

p = re.compile(r'黄色|红|绿',re.M)
for one in  p.findall(content):
    print(one)

 括号-分组

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

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

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


p = re.compile(r'(^.*),', re.MULTILINE)
for one in  p.findall(content):
    print(one)

p1 = re.compile(r'(^.*,)', re.MULTILINE)
for one in  p1.findall(content):
    print(one)

 结果之所以不同是因为,结果是匹配到()当中的。若有多个()则返回把结果放入元组中

content = '''张三,手机号码15945678901
李四,手机号码13945677701
王二,手机号码13845666901'''

p = re.compile(r'^(.+),.+(\d{11})', re.MULTILINE)
for one in  p.findall(content):
    print(type(one))
    print(one)

当有多个分组的时候,我们可以使用 (?P<分组名>...) 这样的格式,给每个分组命名。

这样做的好处是,更方便后续的代码提取每个分组里面的内容

p = re.compile(r'^(?P<name>.+),.+(?P<phone>\d{11})', re.MULTILINE)
for one in  p.finditer(content):
    print(one.group('name'),one.group('phone'))

re.finditer
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回 

让点匹配换行 

众所周知,.(点)是不可以匹配换行符,但有些时候我们需要他完成这一项工作,因此我们需要DOTALL 参数

content = '''
<div class="el">
        <p class="t1">           
            <span>
                <a>Python开发工程师</a>
            </span>
        </p>
        <span class="t2">南京</span>
        <span class="t3">1.5-2万/月</span>
</div>
<div class="el">
        <p class="t1">
            <span>
                <a>java开发工程师</a>
            </span>
		</p>
        <span class="t2">苏州</span>
        <span class="t3">1.5-2/月</span>
</div>
'''

# p = re.compile(r'class=\"t1\">.*<a>(.*)<',re.M)
p = re.compile(r'class=\"t1\">.*<a>(.*)</a',re.DOTALL)
for one in p.findall(content):
    print(one)

 切割字符串

字符串 对象的 split 方法只适用于 简单的字符串分割。 有时,你需要更加灵活的字符串切割。

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

namelist = re.split(r'[;,\s]\s*', names)
print(namelist)

正则表达式 [;,\s]\s* 指定了,分割符为 分号、逗号、空格 里面的任意一种均可,并且 该符号周围可以有不定数量的空格。

字符串替换

匹配模式替换

字符串 对象的 replace 方法只适应于 简单的 替换。 有时,你需要更加灵活的字符串替换。

# 在下面这段文本中 所有的 链接中 找到所以 /avxxxxxx/ 这种 以 /av 开头,
# 后面接一串数字, 这种模式的字符串。

names = '''

下面是这学期要学习的课程:

<a href='https://www.bilibili.com/video/av66771949/?p=1' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是牛顿第2运动定律

<a href='https://www.bilibili.com/video/av46349552/?p=125' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是毕达哥拉斯公式

<a href='https://www.bilibili.com/video/av90571967/?p=33' target='_blank'>点击这里,边看视频讲解,边学习以下内容</a>
这节讲的是切割磁力线
'''

newStr = re.sub(r'/av\d+/', '/cn345677/' , names)
print(newStr)

 

sub 方法就是也是替换 字符串, 但是被替换的内容 用 正则表达式来表示 符合特征的所有字符串。

比如,这里就是第一个参数 /av\d+?/ 这个正则表达式,表示以 /av 开头,后面是一串数字,再以 / 结尾的 这种特征的字符串 ,是需要被替换的。

第二个参数,这里 是 '/cn345677/' 这个字符串,表示用什么来替换。

第三个参数是 源字符串。

 指定替换函数

 

# 替换函数,参数是 Match对象
def subFunc(match):
    # Match对象 的 group(0) 返回的是整个匹配上的字符串, 
    src = match.group(0)
    print(match.group(1))
    
    # Match对象 的 group(1) 返回的是第一个group分组的内容
    number = int(match.group(1)) + 6
    dest = f'/av{number}/'

    print(f'{src} 替换为 {dest}')

    # 返回值就是最终替换的字符串
    return dest

newStr = re.sub(r'/av(\d+?)/', subFunc , names)
print(newStr)

 

正则表达式 re.sub 函数执行时, 每发现一个 匹配的子串, 就会:

  • 实例化一个 match对象

    这个match 对象包含了这次匹配的信息, 比如:整个字符串是什么,匹配部分字符串是什么,里面的各个group分组 字符串是什么

  • 调用执行 sub函数的第2个参数对象,也就是调用回调函数subFunc

    并且把刚才产生的 match 对象作为参数传递给 subFunc

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值