Python 基础(二十二):正则表达式

2020-08-18 10:02:53 浏览数 (1)

1. 简介

正则表达式是一个强大的字符串处理工具,几乎所有的字符串操作都可以通过正则表达式来完成,其本质是一个特殊的字符序列,可以方便的检查一个字符串是否与我们定义的字符序列的某种模式相匹配。

正则表达式并不是 Python 所特有的,几乎所有编程语言都支持正则表达式,Python 提供了内置模块 re 和第三方模块 regex 来支持正则表达式,regex 模块提供了与 re 模块兼容的 API 接口,同时还提供了额外的功能和更全面的 Unicode 支持,本文只介绍 re 模块。

2. 使用

2.1 语法

我们先来熟悉一下正则表达式的基本语法。

代码语言:javascript复制
默认情况,匹配除了换行的任意字符;如果指定了标签 DOTALL,则匹配包括换行符的任意字符

2.2 re 模块

2.2.1 模块内容

re 模块几乎包含了正则表达式的所有功能,我们先来看一下该模块的主要方法。

re.compile(pattern, flags=0)

用于编译正则表达式,生成一个正则表达式(Pattern)对象,供 match() 和 search() 这两个函数使用。参数说明如下:

  • pattern : 一个字符串形式的正则表达式
  • flags : 匹配模式,包括如下:
代码语言:javascript复制
让 w, W, b, B, d, D, s, S 只匹配 ASCII

看一下示例:

代码语言:javascript复制
import re

re.compile(r'abc', re.I)

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

扫描整个字符串找到匹配样式的第一个位置,并返回一个相应的匹配对象;如果没有匹配,就返回一个 None。参数说明如下:

  • pattern:匹配的正则表达式
  • string:要匹配的字符串
  • flags:匹配模式

看一下示例:

代码语言:javascript复制
import re

print(re.search(r'abc', 'abcef'))
print(re.search(r'abc', 'aBcef'))

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

如果 string 开始的 0 或者多个字符匹配到了正则表达式样式,就返回一个相应的匹配对象;如果没有匹配,就返回 None。看下示例:

代码语言:javascript复制
import re

print(re.match(r'abc', 'abcef'))

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

如果整个 string 匹配到正则表达式样式,就返回一个相应的匹配对象;否则就返回一个 None。看一下示例:

代码语言:javascript复制
import re

print(re.fullmatch(r'abc', 'abcef'))
print(re.fullmatch(r'abc', 'abc'))

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

用 pattern 分开 string,如果在 pattern 中捕获到括号,那么所有的组里的文字也会包含在列表里,如果 maxsplit 非零,最多进行 maxsplit 次分隔,剩下的字符全部返回到列表的最后一个元素。看一下示例:

代码语言:javascript复制
import re

print(re.split(r'W ', 'ityard, ityard, ityard.'))
print(re.split(r'(W )', 'ityard, ityard, ityard.'))
print(re.split(r'W ', 'ityard, ityard, ityard.', 1))
print(re.split('[a-f] ', '1A2b3', flags=re.IGNORECASE))

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

对 string 返回一个不重复的 pattern 的匹配列表,string 从左到右进行扫描,匹配按找到的顺序返回,如果样式里存在一到多个组,就返回一个组合列表,空匹配也会包含在结果里。看一下示例:

代码语言:javascript复制
import re

print(re.findall(r'ab', 'abefabdeab'))

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

pattern 在 string 里所有的非重复匹配,返回为一个迭代器 iterator 保存了匹配对象,string 从左到右扫描,匹配按顺序排列。看一下示例:

代码语言:javascript复制
import re

it = re.finditer(r'd ', '12ab34cd56')
for match in it:
    print(match)

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

返回通过使用 repl 替换在 string 最左边非重叠出现的 pattern 而获得的字符串,count 表示匹配后替换的最大次数,默认 0 表示替换所有的匹配。看一下示例:

代码语言:javascript复制
import re

str = 'ityard # 是我的名字'
print(re.sub(r'#.*$', '', str))

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

行为与 re.sub() 相同,但返回的是一个元组。看一下示例:

代码语言:javascript复制
import re

str = 'ityard # 是我的名字'
print(re.subn(r'#.*$', '', str))

re.escape(pattern)

转义 pattern 中的特殊字符。看一下示例:

代码语言:javascript复制
import re

print(re.escape('https://blog.csdn.net/ityard'))

re.purge()

清除正则表达式缓存。

2.2.2 正则对象

来看一下正则表达式对象的相应方法。

Pattern.search(string[, pos[, endpos]])

扫描整个 string 寻找第一个匹配的位置,并返回一个相应的匹配对象,如果没有匹配,就返回 None;可选参数 pos 给出了字符串中开始搜索的位置索引,默认为 0;可选参数 endpos 限定了字符串搜索的结束。看一下示例:

代码语言:javascript复制
import re

pattern = re.compile(r'bc', re.I)
print(pattern.search('aBcdef'))
print(pattern.search('aBcdef', 1, 3))

Pattern.match(string[, pos[, endpos]])

如果 string 的开始位置能够找到这个正则样式的任意个匹配,就返回一个相应的匹配对象,如果不匹配,就返回 None。看一下示例:

代码语言:javascript复制
import re

pattern = re.compile(r'bc', re.I)
print(pattern.match('aBcdef'))
print(pattern.match('aBcdef', 1, 3))

Pattern.fullmatch(string[, pos[, endpos]])

如果整个 string 匹配这个正则表达式,就返回一个相应的匹配对象,否则就返回 None。看一下示例:

代码语言:javascript复制
import re

pattern = re.compile(r'bc', re.I)
print(pattern.fullmatch('Bc'))
print(pattern.fullmatch('aBcdef', 1, 3))

Pattern.split(string, maxsplit=0)

等价于 re.split() 函数,使用了编译后的样式。看一下示例:

代码语言:javascript复制
import re

pattern = re.compile(r'bc', re.I)
print(pattern.split('abc, aBcd, abcde.'))

Pattern.findall(string[, pos[, endpos]])

使用了编译后样式,可以接收可选参数 pos 和 endpos,限制搜索范围。看一下示例:

代码语言:javascript复制
import re

pattern = re.compile(r'bc', re.I)
print(pattern.findall('abcefabCdeABC'))
print(pattern.findall('abcefabCdeABC', 0, 6))

Pattern.finditer(string[, pos[, endpos]])

使用了编译后样式,可以接收可选参数 pos 和 endpos ,限制搜索范围。看一下示例:

代码语言:javascript复制
import re

pattern = re.compile(r'bc', re.I)
it = pattern.finditer('12bc34BC56', 0, 6)
for match in it:
    print(match)

Pattern.sub(repl, string, count=0)

使用了编译后的样式。看一下示例:

代码语言:javascript复制
import re

pattern = re.compile(r'#.*$')
str = 'ityard # 是我的名字'
print(pattern.sub('', str))

Pattern.subn(repl, string, count=0)

使用了编译后的样式。看一下示例:

代码语言:javascript复制
import re

pattern = re.compile(r'#.*$')
str = 'ityard # 是我的名字'
print(pattern.subn('', str))

2.2.3 匹配对象

最后看一匹配对象的相应方法。

Match.expand(template)

对 template 进行反斜杠转义替换并且返回。看一下示例:

代码语言:javascript复制
import re

match = re.match(r'(?P<year>w ) (?P<month>w )','2020 01')
print(match.expand(r'现在是 1 年 2 月'))

Match.group([group1, ...])

返回一个或者多个匹配的子组。看一下示例:

代码语言:javascript复制
import re

match = re.match(r'(?P<year>w ) (?P<month>w )','2020 01')
print(match.group(0))
print(match.group(1))
print(match.group(2))

Match.groups(default=None)

返回一个元组,包含所有匹配的子组,在样式中出现的从 1 到任意多的组合,default 参数用于不参与匹配的情况,默认为 None。看一下示例:

代码语言:javascript复制
import re

match = re.match(r'(?P<year>w ) (?P<month>w )','2020 01')
print(match.groups())

Match.groupdict(default=None)

返回一个字典,包含了所有的命名子组,default 参数用于不参与匹配的组合,默认为 None。看一下示例:

代码语言:javascript复制
import re

match = re.match(r'(?P<year>w ) (?P<month>w )','2020 01')
print(match.groupdict())

Match.start([group])Match.end([group])

返回 group 匹配到的字串的开始和结束标号。看一下示例:

代码语言:javascript复制
import re

match = re.match(r'(?P<year>w ) (?P<month>w )','2020 01')
print(match.start())
print(match.end())

Match.span([group])

对于一个匹配 m,返回一个二元组 (m.start(group), m.end(group))。看一下示例:

代码语言:javascript复制
import re

match = re.match(r'(?P<year>w ) (?P<month>w )','2020 01')
print(match.span())

0 人点赞