python之Re(正则表达式)库入门学习笔记

285 阅读15分钟

python之Re(正则表达式)库入门学习笔记

1,前言

还记否在上面一章中用到了import re,这是正则表达式库,他用什么作用呢,在当时看来他只是用来做检索用的,学习玩下面部分,我们再试着总结出来他的其他作用。

2,正则表达式的概念

2.1,正则表达式

  • regular expression或regex或RE

    有三种叫法,但不管哪一种,都是在说正则表达式。

  • 是用来简洁表达一组字符串的表达式。

    这句话,怎么理解,我试着举出一个例子。

    image

    这是一组字符串,在现在来说表达一组字符串的方式就是将他们一一列举出来,那有没有更方便的呢?有!肯定有!我们看下面的一段代码,虽然现在可能不是很会。

    P(Y|YT|YTH|YTHO)?N
    

    上面一串简单的代码

2.2,正则表达式的优势

我想这个大家会想到一块,两个字,简洁。

正则表达式可以用简单的语法表达很大的一组字符串的特征。正所谓一行胜千言。

这么一说,他 还有一个概念。

  • 表示了一组字符串的特征和模式。

可以用来表达无穷字符串组。

2.3,正则表达式总结

在重新梳理一下正则表达式

  • 通用的字符串表达框架
  • 简洁表达一组字符串的表达式
  • 针对字符串表达”简洁“和”特征“的思想工具
  • 判断某字符串的特征归属

可以看到他们是环环相扣的,因为是框架,所以可以看作是表达式;因为是工具。所以可以用来

2.4,正则表达式作用

正则表达式在文本处理中非常常用。

  • 表达文本的特征( 病毒、入侵等)
  • 同时查找或替换一组字符串
  • 匹配字符串全部或部分内容

可以看出主要在字符串匹配中使用。

2.5,正则表达式使用

为了可以使用正则表达式,我们是需要编译的。什么是编译呢?

  • 编译:将符合正则表达式语法的字符串转换成正则表达式特征。

    可以说正则表达式是某种语法格式,但是在程序中,我们必须有字符串的形式表达它。但是字符串是字符串,他不是一组字符串。因此需要我们编译。将一个字符串编译成一个特征。而这个特征可以表达一组字符串。我们也可以认为,编译后的特征与一组字符串是对应的,而编译之前的正则表达式只是一个符合正则表达式语法的一个单一字符串。但他并不是真正意义上的正则表达式。

3,正则表达式语法

P(Y|YT|YTH|YTHO)?N

这段代码就是正则表达式,是由字符和操作符构成。具体表达什么

3.1,正则表达式的常用操作符

操作符说明举例
.表示任何单个字符
[]字符集,对单个字符给出取值范围[abc]表示a,b,c;[a~z]表示a到z的单个字符。
[^ ]非字符集,对单个字符给出排除范围[^abc]表示非a或b或c的单个字符
*前一个字符0次或无限次扩展abc* 表示ab、abc、abcc、abccc等
+前一个字符1次或无限次扩展abc+ 表示abc,abcc,abcc等
?前一个字符0次或1次扩展abc? 表示ab、abc
左右表达式任意一个abcdef 表示abc、def
{m}扩展前一个字符m次ab{2}c 表示abbc
{m,n}扩展前一个字符m至n次(含n次)ab{1,2}c 表示abc、abbc
匹配字符串开头^abc 表示abc且在一个字符串的开头
$匹配字符串结尾abc$ 表示abc且在一个字符串的结尾
()分组标记,内部只能使用操作符(abc) 表示abc、(abcdef) 表示abc、def
\d数字,等价于[0-9]
\w单词字符,等价于[A-Za-z0-9]

我数了一下,大概差不齐有十四,这些是要熟记的,看几个例子

3.2,正则表达式举例使用

正则表达式对应字符串备注
`P(YYTYTHYTHO)?N`'PN', 'PYN', 'PYTN', 'PYTHN', 'PYTHON',():分组标记 ?:中间括号出现0次或1次
PYTHON+'PYTHON', 'PYTHONN', 'PYTHONNN' ....+:扩展前面字符
PY[TH]ON'PYTON', 'PYHON'[]:给出取值范围
PY[^TH]?ON'PYON', 'PYaON', 'PYbON', 'PYcON' ......[^]:给出排除范围,所以没有'PYTON'和'PYHON ?:对排除范围做了扩展。 ^:
PY{:3}N'PY', 'PYH', PYYN', 'PYYYN'{M,N}:一个扩展区间

有两个我没有整明白,^ and $的作用是什?再下来看一些经典案例

3.3,正则表达式经典案例

正则表达式对应字符串备注
^[A-Za-z]+$有24个字母组成的字符串用区间给出了取值范围,24个字母大小写。
^[A-Za-z0-9]+$有24个字母和数字组成的字符串可以看到区间里多了0~9
^-?\d+$整数形式的字符串考虑到有可能是负数,所以加入负号。对负号进行1次或0次扩展。\d等价于[0-9]
^[0-9]*[1-9][0-9]*$正整数形式的字符串
[1-9]-\d{5}中国境内的邮政编码6位数,第一位不可以为0;
[\u4e00-\u9fa5]匹配中文字符utf-8编码是中文字符,[]是区间的意思
\d{3}-\d{8}\d{4}-\d{7}国内电话号码电话号码前面有的是三位,有的是四位。所以用左右任意一个,但是为什么会有减号。

以上是正则表达式的常用操作符还有他们各自的举例说明,看懂了一半,也有一些没有理解。再看看这些例子,也差不多一半一半。,^ and $从说明来看一个匹配开头,一个匹配结尾,但是还是不是很会。

再看看这些例子,明白其中的原理了吗?可以举一反三吗?既然学习了这个,我想后面肯定会用到。

还有就是如何在python的idle里运行。

4,Re库的基本使用

4.1,Re库介绍

  • Re库是python的标准库,主要用于字符串匹配
  • 调用方式:import re

Re库使用raw string类型来表达正则表达式,我们了解一下

4.2,正则表达式的表示类型

4.2.1,raw string类型

  • 原生字符串类型)

  • Re库采用raw string类型来表达正则表达式,表示为r'text

    r'[1-9]\d{5}'   #中国境内邮政编码r'\d{3}-\d{8}|\d{4}-\d{7}'   #国内电话号码
    

    可以发现原生字符串类型和字符串类型不同的是原生字符串类型前面加个r。

  • raw string类型是不包含转义符的字符串

    意思是在python的语法中会发现有,称解释转义符;而在正则表达式中会频繁的出现,但不解释为转义符。

4.2.2,python string类型,

  • 更繁琐。

为什么会繁琐呢?说到过,正则表达式中会有在``的出现,但不称为转义符。而python string呢?与之相反。所以,但是也可以使用,我们来看看

     r'[1-9]\d{5}'   #中国境内邮政编码     r'\d{3}-\d{8}\|\d{4}-\d{7}'   #国内电话号码

会发现出现的地方都会多了一个

因此:当正则表达式中包含<转义符>时,使用raw string类型

4.3,Re库主要功能函数

Re库的函数有很多,我就介绍一些经常用的。

4.3.1,函数介绍

函数说明
re.search()在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象。
re.match()从一个字符串的开始位置起匹配正则表达式,返回match对象。
re.findall()搜索字符串,以列表类型返回全部能匹配的字符串
re.split()将一个字符串按照正则表达式匹配结果进行分割,返回列表类型。
re.finditer()搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象
re.sub()在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串

主要功能函数,说明还有许多,既然列出来了这六个,一起看看他们是如何使用的

4.3.2,举例说明

(1),re.search()

re.search(pattern, string, fiags=0)
概念及参数

这个函数中有三个参数,看一下

  • pattern:正则表达式的字符串或原生字符串表示

  • string:待匹配字符串

  • fiags:正则表达式使用时的控制标记

    re.I, re.IGNORECASE:忽略正则表达式的大小写,[A-Z]能够匹配小写字符。

    re.M, re.MULTILNE:正则表达式中的^操作符能够将给定字符串的每行当作匹配开始

    re.S, re.DOTALL:正则表达式中的.操作符能够匹配所有字符,默认匹配除换行外的所有字符

代码举例及解析

我们看段代码,理解一下

>>> import re>>> match = re.search(r'[1-9]\d{5}','BIT 100081')>>> if match:    print(match.group(0))​    100081

re.search()函数是用给定的正则来匹配字符串,在这里我们给定的正则是[1-9]\d{5}邮政编码,我们给出的字符串是BIT 100081怎判断match的与否呢?用if语句,之后打印结果。

给出字符串和正则,会按照正则的规则去在字符串里进行筛选,匹配出正确部分。

收获

这是我匹配的手机号码,

image

(2,)re.match()

re.search(pattern, string, fiags=0)
概念及参数

这三个参数在上面的函数中见到过,他们的含义也是相同的。

代码举例及解析
>>> import re>>> match = re.match(r'[1-9]\d{5}', '100081 BIT')>>> if match:    match.group(0)​    '100081'

我们分析一下,和上面的函数进行对比,有一样的地方,也有不一样的。重点是不一样的`'100081 BIT',这里是为什么呢?我们看定义。从一个字符串开始位置进行匹配。就是因为开始位置。如果不是开始位置,则返回为空

image

为什么会用if语句?希望对匹配的结果进行使用的话,需要if语句判断match是否为空,不能用空的函数去调用后面的方法,否则系统报错。

收获

其实和re..search()是很相似的,这个待匹配字符串必须在前面。

(3)re.findall()

re.findall(pattern, string, flags=0)
概念及参数

这三个参数应该已经深入骨髓了吧

代码举例及解析
>>> import re>>> ls = re.findall(r'[1-9]\d{5}', 'BIT100081 TUS100084')>>> ls['100081', '100084']

这类似一个查找,之前我们也用过。

收获

image

他会找这个11,并返回。

(4)re.split()

re.split(pattern, string, maxsplit=0, flags=0)
概念及参数

四个参数其中有三个就不用多说了吧

  • maxsplit:最大分割数,剩余部分作为最后一个元素输出。
代码举例及解析
>>> import re>>> re.split(r'[1-9]\d{5}', 'BIT100081 TUS100084')['BIT', ' TUS', '']

可以直观的看到它去到了匹配的部分,去掉之后的部分分别作为分割的字符元素放到一个列表里。如果我们约束一下

>>> re.split(r'[1-9]\d{5}', 'BIT100081 TUS100084', maxsplit=1)['BIT', ' TUS100084']

因为maxsplit=1,所以分割了一个部分,剩下的作为一个整体放到列表

收获

image

split,我想到了字符串操作中也有这么一个函数方法,起到分割的作用。

(5)re.finditer()

re.finditer(pattern, string, flags=0)
概念及参数

这三个参数同上

代码举例与分析
>>> for m in re.finditer(r'[1-9]\d{5}', 'BIT100081 TUS100084'):	if m:		print(m.group(0))		100081100084

re.findall比较类似,只不过这个不是列表,而是迭代地获得每一次正则表达式匹配的结果。

收获

image

(6)re.sub()

re.sub(pattern, repl, string, count=0, flags=0)
概念及参数

五个参数有两个不认识

  • repl:替换匹配字符串的字符串
  • count:匹配的最大次数
代码举例及分析
>>> re.sub(r'[1-9]\d{5}', ':zipcode', 'BIT100081 TUS100084')'BIT:zipcode TUS:zipcode'

邮政编码被替换成了:zipcode

收获

image

我不知道

4.3.3,总结

image-20210810184528205

以上6个主要函数我分别进行记录与举例。我们需要熟记与学会运用

4.4正则表达式的等价用法

我们可以看作是另一种用法,

1,函数式用法(一次性操作)

>>> rst = re.search(r'[1-9]\d{5}','BIT 100081')

2,面向对象用法(编译后的多次操作)

>>> pat = re.compile(r'[1-9]\d{5}')>>> rst = pat.search('BIT 100081')

这个是用到了re.compile()方法,吧正则赋值给了pat,然后再,仔细发现他是一个道理。一次编译,可以多次操作

3,re.compile()

re.compile(pattern, flage=0)
概念及参数
  • 概念:将正则表达式的字符串形式编译成正则表达式对象。

这两个参数Emmm……

代码片段及解析
>>> regex = re.compile(r'[1-9]\d{5}')

字符串或者原生字符串表示并不是正则表达式,他只是一种表示,如果通过complie编译生成了一个对象regex,这个regex才是正则表达式。它代表了一组字符串。

我们可以通过这样的函数来实现正则表达式表示之间的一个对应,而这种对应使得我们能够更好的理解正则表达式对象的使用方式。经过了complie之后的正则表达式就可以使用它的对象的方法,而这个对象的方法与re库提供的六个操作方法是一致的。

4,Re库的另一种等价用法

函数说明
regex.search()在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象。
regex.match()从一个字符串的开始位置起匹配正则表达式,返回match对象。
regex.findall()搜索字符串,以列表类型返回全部能匹配的字符串
regex.split()将一个字符串按照正则表达式匹配结果进行分割,返回列表类型。
regex.finditer()搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象
regex.sub()在一个字符串中替换所有匹配正则表达式的子串,返回替换后的字符串

在这个六个函数的使用过程中我们需要注意,正是由于前面已经给了regex的正则表达式对象所以在调用这些函数的时候需要其中的将正则表达式那个参数去掉,

5,Re库的match对象

在操作方法中会发现有的返回macth对象,请问什么是match对象。

5.1,match对象

什么是match对象

  • match对象就是一次匹配的结果,它包含了很多匹配的相关信息

看一个例子

>>> match = re.search(r'[1-9]\d{5}','BIT 100081')

search函数的结果保存为match,

>>> if match:	print(match.group(0))	100081

用if语句可以判断match是不是成立

用type类型来检查match类型

>>> type(match)<class 're.Match'>	

match类型

5.2,match对象的属性

属性说明
.string待匹配的文本
.re匹配时使用的pattern对象(正则表达式)
.pos正则表达式搜索文本的开始位置
.endops正则表达式搜索文本的结束 位置

当然有很多属性,我们先介绍4个。

举例。

>>> import re>>> match = re.search(r'[1-9]\d{5}','BIT 100081')>>> if match:	print(match.group(0))	100081

基于以上我们进行举例

>>> match.string'BIT 100081'

输出我们匹配的字符串

>>> match.rere.compile('[1-9]\d{5}')

是不是很熟悉,注意这个正则表达式带有compile标识的。说明在程序内部以为只有经过compile之后的正则表达式才是一个正则表达式。没有经过compile的正则表达式仅仅是正则表达式的一种表示。

>>> match.pos0

从第0个字符串开始

>>> match.endpos10

在第10个字符串结束

5.3,match对象的方法

属性说明
.group()获得匹配后的字符串
.start()匹配字符串在原生字符串的开始位置
.end()匹配字符串在原生字符串的结束位置
.span()返回(.start(), .end())

同样我们进行举例。

>>> match.group(0)'100081'

匹配后的结果会放在.group(0)内容中,注意他只包含一次的匹配结果

>>> match.start()4

匹配结果在原字符串的起始位置

>>> match.end()10

匹配结果在原字符串的终止位置

>>> match.span()(4, 10)

这两个位置的二元关系。

6,re库的贪婪匹配和最小匹配

这个是什么意思呢?我们先看一段例子。

>>> import re>>> match = re.search(r'PN.*N', 'PYANBNCNDN')>>> match.group(0)

我们用到的正则表达式是r'PN.*N'以PY字母开头以N结尾,中间可以有若干个字符串。我们匹配的字符串是'PYANBNCNDN'

这样一个正则表达式,可以在给定字符串中存在多个匹配项,这里面有四个匹配项,怎么说,

运行后出现的结果可能会有PYANPYANBNPYANBNCNPYANBNCNDN他们的长短也不一样。最短的只有4个字符,最长的是整个字符串。

同时匹配长短不同的项,返回哪一个呢?

6.1,贪婪匹配

  • Re库默认采用贪婪匹配,即输出匹配最长的字符串

    >>> match = re.search(r'PY.*N', 'PYANBNCNDN')>>> match.group(0)'PYANBNCNDN
    

    look,返回匹配最长的字符串

6.2,最小匹配

有时候我们只需要匹配最小的,不需要那么长,怎么办呢,

>>> match = re.search(r'PY.*?N', 'PYANBNCNDN')>>> match.group(0)'PYAN

你会发现我们在正则部分动了写手脚,将r'PY.*N'改成了r'PY.*?N'

6.3,最小匹配操作符

操作符说明
*?前一个字符0次或无限次扩展,最小匹配
+?前一个字符1次或无限次扩展,最小匹配
??前一个字符0次或1次扩展,最小匹配
{m,n}?扩展前一个字符m至n(含n),最小匹配

当我们匹配的字符串会出现很多项时,我们就可以进行限制

7,总结

正则表达式用来做什么?处理文本。或许还有其他的应用场景,在此不做过多了解。这一章学习中简单的明白了正则表达式和他们的用法,如何处理一段文本。这项知识还有很多,我们在以后的日子里还需要学习。

这就是以上内容,我的笔记。

谢谢您的,文章有错误,欢迎你的指正;如果对您有帮助,是我的荣幸。

\