Python正则表达式和模式匹配

一、正则表达式简介

1.1 用途

  • 表达文本类型的特征(病毒、特征等)
  • 同时查找或替换一组字符
  • 匹配字符串的全部或部分(最重要的功能)

1.2 常用操作符

正则表达式由字符和操作符(元字符)构成。

操作符 说明 实例
. 表示任何单个字符
[ ] 字符集,对单个字符给出取值范围 [abc] 表示 a、b、c,[a-z] 表示 a 到 z 的单个字符
[^] 非字符集,对单个字符给出排除范围 [^abc] 表示非 a、b、c 的单个字符
* 前一个字符0次或无限次扩展 abc* 表示 ab、abc、abcc...
+ 前一个字符1次或无限次扩展 abc+ 表示 abc、abcc...
? 前一个字符0次或1次扩展 abc? 表示 ab 和 abc
| 操作符两侧表达式任意一个 abc|def 表示 abc 和 def
{m} 扩展{}前面的一个字符 ab{2}c 表示 abbc
{m,n} 扩展前一个字符 m 到 n 次(包含 m、n) ab{1,2}c 表示 abc、abbc
^ 匹配字符串开头 ^abc 表示以 abc 开头的字符串
\(|匹配字符串结尾|`abc\)表示以 abc 结尾的字符串| |( )|分组标记,且( )内只能使用 |(abc)表示 abc,(abc def)表示 abc、def| |\d|数字,等价于[0-9]|| |\w|单词字符,等价于[A-Za-z0-9_]`
(?Pword) 可以使匹配的字符串可以在后面的程序中通过组名符号来引用 看下面的代码示例。官网说明请访问 Regular Expression HOWTO
1
2
3
4
5
6
7
8
9
import re

string = "The quick brown fox jumps over the lazy dog."
string_list = string.split()
pattern = re.compile(r"(?P<match_word>The)",re.I)

print("Output #39:")for word in string_list:
if pattern.search(word):
print("{0:s}".format(pattern.search(word).group('match_word')))

1.3 经典正则表达式实例

表达式 含义
^[A-Za-Z]+$ 由26个字母组成的字符串
^[A-Za-z0-9]+$ 由26个字母和数字组成的字符串
^-?\d+$ 整数形式的字符串
^\d+$ 正整数形式的字符串
[1-9]\d{5} 中国境内邮政编码,6位(这个有问题的,起码可以是0开头)
[\u4e00-\u9fa5] 匹配中文字符
\d{3}-\d{8}|\d{4}-\d{7} 中国境内电话号码

1.4 匹配 IP 地址

IP 地址分4段,每段的取值范围是0-255。正则表达式精确表示形式:

1
2
3
4
5
6
7
8
0-99:[1-9]?\d
100-1991\d{2}
200-2492[0-4]\d
250-25525[0-5]

# 完整的 IP 地址表达方式:

(([1-9]?\d)|(1\d2)|(2[0-4]\d)|(25[0-5])){3}.(([1-9]?\d)|(1\d2)|(2[0-4]\d)|(25[0-5]))

1.5 贪婪匹配和最小匹配

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

最小匹配,输出匹配最短的子串

最小匹配操作符

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

二、Re 库的使用

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

2.1 正则表达式的表示类型

  • raw string 类型(原生字符串类型),是不包含对转义符再次转义的字符。表示为 r'text'
  • string 类型,更加繁琐。例如 raw string 类型表示电话号码 \d{3}-\d{8}|\d{4}-\d{7},string 类型则需要增加转义符 \\d{3}-\\d{8}|\\d{4}-\\d{7}

2.2 Re 库主要功能函数

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

2.2.1 语法

1
2
3
4
5
6
7
8
9
10
11
re.search(pattern,string,flags=0)

re.match(pattern,string,flags=0)

re.findall(pattern,string,flags=0)

re.split(pattern,string,maxsplit=0,flags=0)

re.finditer(pattern,string,flags=0)

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

说明:

  • pattern:正则表达式的字符串或原生字符串表示
    • pattern 中经常会使用一个原始字符串标志 r,可以确保 Python 不处理字符串中的转义字符(如、)
  • string:待匹配字符串
  • flags:正则表达式使用时的控制标记
  • maxsplit:最大分割数,剩余部分作为最后一个元素输出
  • repl:替换匹配字符串的字符串,用 repl 替换 pattern
  • count:匹配的最大替换次数

2.2.2 常用控制标记

flags常用标记 说明
re.Ire.IGNORECASE 忽略正则表达式的大小写,[A-Z]能匹配 a-z
re.Mre.MULTILINE 正则表达式中的^能够将给定的字符串的每行当做匹配开始
re.Sre.DOTALL 正则表达式中 . 操作符能匹配所有字符,默认匹配除换行外的所有字符

注意:对匹配的结果进行使用时,必须用 if 语句进行判断匹配结果(match 对象或列表)是否为空 ,否则对空字符串进行操作会报错“ ”

示例代码:14’25’’

2.3 Re 库的两种使用方法

2.3.1 函数式用法

前面所讲的,都是 Re 库的第一种用法——函数式用法:一次性操作

1
Rst = re.search(r'\d{3}-\d{8}|\d{4}-\d{7}’,'我的电话 010-02145324')

2.3.2 面向对象用法

现在我们来介绍第二种用法——面向对象用法:编译后多次使用

比如前面的例子中,用面向对象的写法如下所示:

1
2
patt = re.compile(r'\d{3}-\d{8}|\d{4}-\d{7}')
rst = pat.search('我的电话 010-02145324')

将正则表达式的字符串形式编译成正则表达式对象:

1
regex = re.compile(pattern,flags)

面向对象用法的功能函数由于函数用法中的pattern 已经编译成 regex,所以下面6个函数使用时需要去掉 pattern 参数。即 regex.search(string,flags)

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

三、Re 库的 match 对象

re 库运行后返回的是 match 对象。

3.1 match 对象的属性

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

3.2 match 对象的方法

方法 说明
.group(0) 获得匹配后的字符串。(一般使用就这个 .group(0) 就足够了)
.start() 匹配字符串在原始字符串的开始位置
.end() 匹配字符串在原始字符串的结束位置
.span() 返回(.start(), .end())

示例:

示例.png
示例.png