【Python 基础篇】Python正则表达式及 re 库

正则表达式,一个强大的规则。在python中,正则表达式涉及的库主要有:xpath、bs4、re 。今天,我们主要讲述re库。

字符串操作是我们不管学习哪种脚本语言,都涉及的。不管是爬虫,还是数据表格处理,都离不开字符串操作。然而,在字符串章节的内容中,我们已经知道,字符串内建函数也是挺丰富的。一定程度上,也能够满足我们的项目需求。但是,学会了正则,我们在字符串处理上面,更加灵活自如,如鱼得水。

原文链接:https://blog.csdn.net/weixin_44051713/article/details/93162249   此文转载,仅用于个人学习,感谢大佬分享!!!

一  正则表达式是什么

正则表达式是一组特殊的字符序列、是对字符串操作的一种逻辑公式。

正则表达式通常被用来检索、替换那些符合某个模式的文本。比如检测一串数字是否符合电话号码、检测一个字符串是否符合email标准,实现诸如此类的对于字符串或者是文本的操作都可用正则表达式实现,正则表达式的功能是非常强大的,掌握正则表达式也是非常重要的。

二  元字符是什么

首先,

import re
string='JavaScript|.Net|Java|Python'
re.findall("正则表达式",string)

在上面代码中,如果我们想要匹配到Python,我们直接可以在正则表达式中直接写入Python,他便会返回一个结果列表,这就是正则最基本的用法,这样的结果并没有意义,因为我们填写的是一个常量字符串,并没有把正则的规则和意义体现出来,正则表达式最重要的就是规则。

其次, 

import re
string='Pyth4on|J5av2a12Script|5.Net|Ja2va'
re.findall("正则表达式",string)

现在有这么一个问题,要求在string字符串中匹配出所有的数字,那么如果我们用刚刚的常量字符串,那么只能写成:

re.findall("0",string)
re.findall("1",string)
re.findall("2",string)
...

最后,

 这样显然也是没有意义的,那该怎么办呢,正则表达式提供了一个抽象的符号 ‘/d’ 代表0-9的任何数字。

import re
string='Pyth4on|J5av2a12Script|5.Net|Ja2va'
result=re.findall("\d",string)
print(result)

总结,

这样 我们就把该字符串里的所有字符匹配出来了,然后我们回过头来思考一下正则表达式的定义,正则表达式是一组特殊的字符序列,所以正则表达式最终要落入字符这里,之前的我们写的直接匹配Python的字符串,我们的正则表达式就会给他构造一个类型 叫做普通字符 对于这样的一个 ‘/d’ 我们把它叫做元字符 我们的正则表达式就是用一系列的普通字符元字符组成的,普通字符并没什么可讲性,他就是你看到这样的实实在在的字符,它就是具体的字符,所以我们应该主要学习的就是元字符。
正则表达式中有特别多的元字符 如下图(简略的介绍):

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

如此多的元字符,是不是头皮发麻了,其实千万不要想着把这些背下来,我们只要根据自己的业务需求,然后将元字符组合成你需要的就可以了,其实日常用的元字符并不多。

三  字符集

学习了元字符相信大家对正则表达式有初步了解.

接下来我要讲解的知识点就是:正则表达式主要模式之一,字符集 接下来看一个例子:

import re
string='cat,dog,bat,log,sit,pig'
result=re.findall("正则表达式",string)
print(result)

要求:匹配出所有中间字母为o或i的字母,重点是这个  字。
很明显我们不能使用普通字符来匹配,所以我们现在又要用一种抽象来概括 o 和 i 这就是我们字符集的使用,其实很简单:

import re
string='aac,abc,aic,aoc,azc,awc'
result=re.findall("a[io]c",string)
print(result)

我们的字符集用的是 [ ] ,然后把我们要抽象的字符集写在中括号里。这里我们还用了普通字符如果没有普通字符来给我们定界的话,我们无法直接筛选出我们想要的字符的(大家可以试一下) 下面跟大家解释一下字符集的特性:

(1)出现在中括号里面的字符是 关系
(2)他还有另外一个用法:比如匹配除了中间字符为i和o的字符 我们只需要在中括号里面加一个 上尖角 ^
(3)还要一个小技巧,比如我们要匹配的字符太多的话,比如要匹配 bcdefghi 这样的字符集 我们可以直接在中括号里面写 [b-i] 他就可以这这些全部匹配出来了。

四  概括字符集应用

什么叫概括字符集呢?
比如我们之前学的元字符 \d 他就是一个概括字符集 他可以用字符集写成[0-9] \d就是对他的一种概括(其实有很多叫法) 因为正则表达式是非常灵活的,比如我们刚刚做的匹配数值的哪一题也可以写成:

import re
string='Pyth4on|J5av2a12Script|5.Net|Ja2va'
result=re.findall("[\d]",string)
print(result)

五  数量词应用

在我们下列案例中有这么一个问题:

import re
string='Ja5va|Pyth4on|JavaSc1ript|.Ne6t'
result=re.findall("[a-z]",string)
print(result)
输出#['a', 'v', 'a', 'y', 't', 'h', 'o', 'n', 'a', 'v', 'a', 'c', 'r', 'i', 'p', 't', 'e', 't']

你会发现他会把这些单词拆分成一个字母,不管是字符集也好还是元字符也好,他们只能表示一个字符,那如何合成一个单词呢,可能有些人会想出这种办法:

import re
string='python 11java899php'
result=re.findall("[a-z][a-z][a-z]",string)
print(result)
#['pyt', 'hon', 'jav', 'php']

多写几个字符集
那么如果是100个字符呢,所以这种方式肯定是不可取的
那该怎么办呢,这就引出了我们的数量词

import re
string='python 11java899php'
result=re.findall("[a-z]{3}",string)
print(result)
#['pyt', 'hon', 'jav', 'php']

这就是数量词的用法,他可以吧前面的字符重复N次或者N到M次
在上面案例中 花括号3,6 表示匹配符合规则的字符3-6次 其实当匹配到第三次的时候就已经符合匹配规则了,那么他为什么还要继续匹配呢???
这就涉及到一个比较重要的概念(贪婪和非贪婪),接下来我会讲解。

六  贪婪与非贪婪

什么是贪婪模式?

比如我们把匹配规则定义在一个区间内 他会尽可能多的去匹配符合规则的字符。

非贪婪反之。
python默认的匹配模式是贪婪模式
非贪婪如何表示?
在数量词后面添加一个"?" 这样就表示非贪婪模式 如下(同样是上一题):

import re
string='python 11java899php'
result=re.findall("[a-z]{3,6}?",string)
print(result)
#['pyt', 'hon', 'jav', 'php']

在原理上很简单,但是在具体正则使用的时候贪婪和非贪婪会经常产生一些程序bug的,这个要着重注意的,特别的入门不久的新手
数量词还包括 *(匹配前面字符0次或多次) +(匹配前面字符1次或者多次)

七  三方库re提供的一些方法

注:
re模块的正则表达式相关函数中都有一个flags参数,它代表了正则表达式的匹配标记,可以通过该标记来指定匹配时是否忽略大小写、是否进行多行匹配、是否显示调试信息等。

其中一个常用可选参数,flags=re.IGNORECASE,表示匹配的时候忽略字符串大小写。如:

方法名字举例注意事项
re.match()match(pattern, string)

从字符串的起始位置开始匹配,如果匹配成功,则返回匹配字符串。如果匹配不成功,则返回None。注意:一定是从头开始匹配,中间匹配成功不算。然而前面匹配到了后,后边多出来的字符就不管了。

print(re.match(r'The', 'The world is ...'))
print(re.match(r'world', 'The world is ...'))

结果:
<re.Match object; span=(0, 3), match='The'>
None
 

re.fullmatch()fullmatch(pattern, string)

字符串从头匹配到尾,匹配成功才会返回正则表达式对象。也就是说,后边多出来的字符串他也要管,发现没匹配到,直接返回None。

实例:

print(re.fullmatch(r'The', 'The world is ...'))
print(re.fullmatch(r'The.*', 'The world is ...'))
结果:

None
<re.Match object; span=(0, 16), match='The world is ...'>
第一行代码放在match那边就能匹配成功,在这儿却返回None,足以表明了fullmatch匹配更为严苛,需要从头到尾匹配。

re.search()search(pattern, string)

search和findall和上边的match和matchall的最重要差别是,search和findall不管头不管尾,只要在中间有地方匹配到了,就匹配成功了,看这方法名也可以看出匹配的严格程度较低

# 下面正则表达式的意思是,先匹配一个下划线,然后匹配一个任意的(字母/数字/下划线)

print(re.search(r'_\w', 'The_world_is_...'))

<re.Match object; span=(3, 5), match='_w'>

re.compile()re.compile(pattern, flags=0)

pattern 指定编译时的表达式字符串
flags 编译标志位,用来修改正则表达式的匹配方式。支持 re.L|re.M 同时匹配
flags 标志位参数:

re.I(re.IGNORECASE) :使匹配对大小写不敏感
re.L(re.LOCAL) :做本地化识别(locale-aware)匹配
re.M(re.MULTILINE) :多行匹配,影响 ^ 和 $
re.S(re.DOTALL) :使 . 匹配包括换行在内的所有字符
re.U(re.UNICODE):根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X(re.VERBOSE):该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

re.findall()findall(pattern, string)

search和findall和上边的match和matchall的最重要差别是,search和findall不管头不管尾,只要在中间有地方匹配到了,就匹配成功了,看这方法名也可以看出匹配的严格程度较低

print(re.findall(r'_\w', 'The_world_is_...'))

['_w', '_i']

re.finditer(pattern, string[, flags])搜索string,返回一个顺序访问每一个匹配结果的迭代器
re.subre.sub(patternreplstringcount=0flags=0)

对于输入的一个字符串,利用正则表达式(的强大的字符串处理功能),去实现(相对复杂的)字符串替换处理,然后返回被替换后的字符串。

inputStr = "hello 123 world 456"

replacedStr = re.sub("\d+", "222", inputStr)

re.subn

re.sub(pattern, repl, string, count=0, flags=0)

re.subn(pattern, repl, string, count=0, flags=0)

参数:

1)pattern:匹配的正则表达式;

2)string:搜索文本字符串

3)repl:替换对象,将搜索文本中和模式匹配的字符串替换为repl对象对应的内容,repl可以是,或者是字符串一个函数

4)count:用于限制最多替换多少次,为0或者没有传入则全部替换;

5)flags:搜索标记,与《第11.2节 Python 正则表达式支持函数概览》介绍的参数flags标记含义相同。

返回值:

sub返回通过使用 repl 替换在通过正则表达式模式搜索到的字符串。 如果没有找到匹配子串,则直接返回 string。

subn与sub函数一样执行搜索替换,但是不是返回替换后的字符串,而是返回一个元组,元组的第一个元素是替换后的字符串(该元素与sub返回值相同),第二个元素是执行替换的次数。
 

re.splitsplit(pattern,string)

re模块里的split方法具有匹配正则表达式然后进行分割的功能,而字符串.split方法,不能通过正则表达式分割字符串。

# 这里正则表达式的意思是,先匹配一个下划线后再匹配一个任意字符
print(re.split(r'_.', 'The_world_is_...'))
# 试图通过正则表达式来分割字符串
print('The_world_is_...'.split(r'_\w'))
# 使用普通的字符串来分割
print('The_world_is_...'.split(r'_'))

结果:

['The', 'orld', 's', '..']
['The_world_is_...']
['The', 'world', 'is', '...']

re.group
 1 >>> a="123abc456"
 2 >>> import re
 3 >>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(0))
 4 123abc456
 5 >>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(1))
 6 123
 7 >>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(2))
 8 abc
 9 >>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group(3))
10 456
11 >>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).group())
12 123abc456
13 >>> print(re.search("([0-9]*)([a-z]*)([0-9]*)", a).groups())
14 (‘123‘, ‘abc‘, ‘456‘)
15 >>> print(re.search("([0-9])*([a-z])*([0-9]*)", a).groups())
16 (‘3‘, ‘c‘, ‘456‘)
17 >>> print(re.search("([0-9])*([a-z])*([0-9]*)", a).groups(1))
18 (‘3‘, ‘c‘, ‘456‘)
19 >>> print(re.search("([0-9])*([a-z])*([0-9]*)", a).group(0))
20 123abc456
21 >>> print(re.search("([0-9])*([a-z])*([0-9]*)", a).group())
22 123abc456

  1. 正则表达式中的三组括号把匹配结果分成三组

    m.group() == m.group(0) == 所有匹配的字符(即匹配正则表达式整体结果)
    group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分,group(3) 列出第三个括号匹配部分。
    m.groups() 返回所有括号匹配的字符,以tuple格式。m.groups() == (m.group(0), m.group(1), …)

  2. 没有匹配成功的,re.search()返回None

  3. 当然郑则表达式中没有括号,group(1)肯定不对了。

在正则表达式中,re.group()方法是用来提取出分组截获的字符串,匹配模式里的括号用于分组.

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
 
if __name__ == '__main__':
    # 匹配模式
    test_pattern = r"(\d{2}年)(\d{4}年)(\d{4}年)"
    # 待匹配的字符串
    test = "18年2019年2020年"
    # 整体匹配结果
    print(re.search(test_pattern, test).group())
    # 整体匹配结果
    print(re.search(test_pattern, test).group(0))
    # 第一个括号处
    print(re.search(test_pattern, test).group(1))
    # 第二个括号处
    print(re.search(test_pattern, test).group(2))
    # 第三个括号处
    print(re.search(test_pattern, test).group(3))

结果:

18年2019年2020年
18年2019年2020年
18年
2019年
2020年
 
Process finished with exit code 0


 

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Python中的re模块提供了一种用于处理正则表达式的工具。其中,compile函数可以将正则表达式编译为一个正则对象,从而提高正则表达式的效率。 compile函数的语法如下: re.compile(pattern, flags=0) 其中,参数pattern代表要编译的正则表达式,flags代表可选的标志位,用于控制正则表达式的匹配方式。 使用compile函数可以将多次使用的正则表达式进行编译,从而提高程序的效率。在实际开发中,如果需要对一个字符串进行多次匹配操作,建议使用compile函数预编译正则表达式。 例如,假设要匹配所有以字母开头、后跟数字字符串,可以使用如下代码: ```python import re # 编译正则表达式 pattern = re.compile(r"[a-zA-Z]\d+") # 匹配字符串 result = pattern.findall("A123 B456 C789") print(result) # 输出: ['A123', 'B456', 'C789'] ``` 在上面的代码中,首先使用compile函数编译了正则表达式r"[a-zA-Z]\d+",然后使用findall方法匹配字符串"A123 B456 C789",返回了所有符合条件的子串。 总之,compile函数是一个非常有用的正则表达式工具,可以提高正则表达式的效率,减少不必要的匹配操作,从而在实际开发中发挥作用。 ### 回答2: 在Python中,re模块是用于正则表达式操作的标准。而re中的compile函数是用于将字符串形式的正则表达式编译成一个正则表达式对象,以便在之后的匹配中可以直接使用该对象。 使用compile函数编译正则表达式可以提高匹配效率,特别是在需要重复匹配同一个表达式时。因为每次使用正则表达式匹配都需要重新构建正则表达式的解析树,而使用compile函数编译正则表达式就可以把解析树缓存起来,在需要匹配时可以直接调用缓存的解析树,从而提高了匹配效率。 具体使用方法,可以先使用compile函数将正则表达式编译成一个对象,然后使用该对象的match、search、findall等方法进行匹配操作。例如: import re pattern = re.compile(r'\d+') # 编译正则表达式 result = pattern.findall('hello123world456') # 使用编译后的正则表达式对象进行匹配 print(result) # ['123', '456'] 另外需要注意的是,使用compile函数编译的正则表达式对象是可以重复使用的,因此在需要多次匹配同一个表达式时,可以先编译成对象,然后重复调用该对象的方法进行匹配操作,可以避免重复编译的影响。 ### 回答3: 在Python中,re模块可以用来处理正则表达式。compile()函数是re模块的一个方法,它可以将一个正则表达式串编译成一个pattern对象,这个对象可以再次被用来处理字符串。 使用re.compile()函数的一个主要原因是它可以提高代码的执行效率。如果需要多次使用同一正则表达式,如果每次都要编译一遍,就会浪费很多时间。如果编译一次之后,将pattern对象保存在一个变量中,就可以在需要时多次使用,提高了程序的运行速度。 compile()函数有两个参数:pattern和flags。其中,pattern表示要编译的正则表达式字符串,flags是一个可选的参数,用来指定正则表达式的匹配模式。flags可以是一组位标志,也可以是具体的某个标志。 注意,使用re.compile()创建的pattern对象只支持基本的正则表达式语法。如果需要使用进阶的语法,比如lookahead或lookbehind,就必须使用re模块中的其他函数。 下面是一个使用compile()函数的简单示例: import re pattern = re.compile(r'\d+') # 匹配所有数字 text = 'there are 123 apples' match = pattern.search(text) if match: print(match.group()) # 输出 123 上面的代码首先用compile()函数创建了一个正则表达式对象,表示匹配所有数字。然后它在文本中搜索这个对象,如果匹配成功,就通过group()方法输出匹配的文本。 总之,compile()函数是Python正则表达式的重要组成部分。它可以将需要多次使用的正则表达式对象编译成pattern对象,从而提高程序的效率。使用compile()函数还可以更方便地管理正则表达式,使得代码更加易读易维护。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值