Python RE模块(正则表达式)
就其本质而言,正则表达式(或 RE)是一种小型的、高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现。正则表达式模式被编译成一系列的字节码,然后由用 C 编写的匹配引擎执行。
方法 | 说明 | 表达式实例 | 完整匹配的字符串 |
---|---|---|---|
一般字符 | 匹配自身 | abc | abc |
. | 匹配除' '之外的任意字符. | a.c | abc |
|转义字符,使后一个字符改变原来的意思 | a.c ac |
a.c ac |
|
[] | 字符集,对应位置可以是字符集中的任意字符. 字符集中的字符可以逐个列出,也可列出范围, 如[abc]或[a-c],如果第一个字符为则表示取反,<br>如[abc]表示不是abc的其它字符 |
a[bcd]e | abe ace ade |
数量 | |||
* | 匹配前一个字符0次或多次 | abc* | ab abc |
+ | 匹配前一个字符1次或多次 | abc+ | abc abcc |
? | 匹配前一个字符0次或1次 | abc? | ab abc |
{m} | 匹配前一个字符m次 | abc{2} | abcc |
{m,n} | 匹配前一个字符最少m次,最多n次 | ab{1,3}c | abc abbbc |
{m,} | 匹配前一个字符最少m次 | ab{1,}c | abc abbbbc |
{,n} | 匹配前一个字符最多n次 | ab{,3}c | ac abbbc |
*?,+?,??,{m,n}? | *,+,?等都是贪婪匹配,也就是尽可能匹配, 后面加?号使其变成惰性匹配 |
||
边界匹配 | |||
^ | 匹配以xxx字符串开头 在多行模式中匹配每一行开头 |
^abc | abcdef |
$ | 匹配以xxx字符串结尾 在多选模式中匹配每一行结尾 |
abc$ | defabc |
预定义字符集 | |||
d | 数字:[0-9] | adc | a1c |
D | 非数字:[^d] | aDc | abc |
s | 空白字符:[空格 fv] | asc | a c |
S | 非空白字符:[^s] | aSc | abc |
w | 单词字符:[a-zA-Z0-9] | awc | abc |
W | 非单词字符:[^w] | aWc | a c |
数量词的贪婪模式与非贪婪模式
正则表达式通常用于在文本中查找匹配的字符串。Python里数量词默认是贪婪的(在少数语言里也可能是默认非贪婪),总是尝试匹配尽可能多的字符;非贪婪的则相反,总是尝试匹配尽可能少的字符。例如:正则表达式"ab*"如果用于查找"abbbc",将找到"abbb"。而如果使用非贪婪的数量词"ab*?",将找到"a"。
反斜杠的困扰
与大多数编程语言相同,正则表达式里使用""作为转义字符,这就可能造成反斜杠困扰。假如你需要匹配文本中的字符"",那么使用编程语言表示的正则表达式里将需要4个反斜杠"\":前两个和后两个分别用于在编程语言里转义成反斜杠,转换成两个反斜杠后再在正则表达式里转义成一个反斜杠。Python里的原生字符串很好地解决了这个问题,这个例子中的正则表达式可以使用r""表示。同样,匹配一个数字的"d"可以写成r"d"。有了原生字符串,你再也不用担心是不是漏写了反斜杠,写出来的表达式也更直观。
RE中模块的一些方法(函数)
Match对象是一次匹配的结果,包含了很多关于此次匹配的信息,可以使用Match提供的可读属性或方法来获取这些信息。
属性:
string: 匹配时使用的文本。
re: 匹配时使用的Pattern对象。
pos: 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
endpos: 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
lastindex: 最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
lastgroup: 最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
方法:
group([group1, …]):
获得一个或多个分组截获的字符串;指定多个参数时将以元组形式返回。group1可以使用编号也可以使用别名;编号0代表整个匹配的子串;不填写参数时,返回group(0);没有截获字符串的组返回None;截获了多次的组返回最后一次截获的子串。
groups([default]):
以元组形式返回全部分组截获的字符串。相当于调用group(1,2,…last)。default表示没有截获字符串的组以这个值替代,默认为None。
groupdict([default]):
返回以有别名的组的别名为键、以该组截获的子串为值的字典,没有别名的组不包含在内。default含义同上。
start([group]):
返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。
end([group]):
返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。
span([group]):
返回(start(group), end(group))。
expand(template):
将匹配到的分组代入template中然后返回。template中可以使用id或g
match:
# match,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None
match(pattern, string, flags=0)
# pattern: 正则模型
# string : 要匹配的字符串
# falgs : 匹配模式
X VERBOSE Ignore whitespace and comments for nicer looking RE's.
I IGNORECASE Perform case-insensitive matching.
M MULTILINE "^" matches the beginning of lines (after a newline)
as well as the string.
"$" matches the end of lines (before a newline) as well
as the end of the string.
S DOTALL "." matches any character at all, including the newline.
A ASCII For string patterns, make w, W, , B, d, D
match the corresponding ASCII character categories
(rather than the whole Unicode categories, which is the
default).
For bytes patterns, this flag is the only available
behaviour and needn't be specified.
L LOCALE Make w, W, , B, dependent on the current locale.
U UNICODE For compatibility only. Ignored for string patterns (it
is the default), and forbidden for bytes patterns.
import re
# 无分组
text = 'hellooldboyhelloworld'
r = re.match("hw+", text)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组结果
# 有分组
# 为何要有分组?提取匹配成功的指定内容(先匹配成功全部正则,再匹配成功的局部内容提取出来)
r = re.match("h(w+).*(?P<name>d)$", text)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组
search:
# search,浏览整个字符串去匹配第一个,未匹配成功返回None
# search(pattern, string, flags=0)
import re
# 无分组
text = 'abcd123efghiARGFD'
r = re.search("aw+", text)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组结果
# 有分组
r = re.search("a(w+).*(?P<name>d)$", text)
print(r.group()) # 获取匹配到的所有结果
print(r.groups()) # 获取模型中匹配到的分组结果
print(r.groupdict()) # 获取模型中匹配到的分组中所有执行了key的组
findall:
# findall,获取非重复的匹配列表;如果有一个组则以列表形式返回,且每一个匹配均是字符串;如果模型中有多个组,则以列表形式返回,且每一个匹配均是元祖;
# 空的匹配也会包含在结果中
#findall(pattern, string, flags=0)
# 无分组
r = re.findall("aw+",text)
print(r)
# 有分组
text = "hello alex bcd abcd lge acd 19"
r = re.findall("a((w*)c)(d)", text)
print(r)
sub:
# sub,替换匹配成功的指定位置字符串
sub(pattern, repl, string, count=0, flags=0)
# pattern: 正则模型
# repl : 要替换的字符串或可执行对象
# string : 要匹配的字符串
# count : 指定匹配个数
# flags : 匹配模式
# 与分组无关
origin = "hello alex bcd alex lge alex acd 19"
r = re.sub("aw+", "999", origin, 2)
print(r)
split:
# split,根据正则匹配分割字符串
split(pattern, string, maxsplit=0, flags=0)
# pattern: 正则模型
# string : 要匹配的字符串
# maxsplit:指定分割个数
# flags : 匹配模式
# 无分组
origin = "hello alex bcd alex lge alex acd 19"
r = re.split("alex", origin, 1)
print(r)
# 有分组
origin = "hello alex bcd alex lge alex acd 19"
r1 = re.split("(alex)", origin, 1)
print(r1)
r2 = re.split("(al(ex))", origin, 1)
print(r2)