一、正则表达式介绍
1.正则表达式一种用来匹配字符串的强有力武器,用一种描述性的语言来给字符串定义一个规则,凡是符合规则的字符串,就认为它“匹配”了,否则,该字符串就是不合法的
2.正则表达式是高级的字符串匹配处理方式
3.正则表达式的原理:通过描述匹配内容的类型和长度来获取字符串当中的指定字符
二、正则表达式的划分
1.对类型的描述
(1)原样匹配
通常原样匹配会结合其他匹配一起出现
r''或者r"",表示中间的部分就是全部的原含义,没有任何的特殊含义
原样匹配,通常会结合其他匹配一起出现
import re
str_ = "suner suner"
str_1 = re.findall(r"u",str_)
print(str_1) # 结果:['u', 'u']
(2). 匹配,匹配所有非换行的字符
import re
str_ = "suner yao xue xi"
str_1 = re.findall(r".", str_)
str_2 = re.findall(r"..", str_)
str_3 = re.findall(r"...", str_)
str_4 = re.findall(r"....", str_)
print(str_1) # 结果:['s', 'u', 'n', 'e', 'r', ' ', 'y', 'a', 'o', ' ', 'x', 'u', 'e', ' ', 'x', 'i']
print(str_2) # 结果:['su', 'ne', 'r ', 'ya', 'o ', 'xu', 'e ', 'xi']
print(str_3) # 结果:['sun', 'er ', 'yao', ' xu', 'e x']
print(str_4) # 结果:['sune', 'r ya', 'o xu', 'e xi']
(3)\ 转义,将特殊字符的特殊含义转义掉,变为一个普通的匹配字符串
import re
str_ = "zhe ge shi 20.000.00"
str_1 = re.findall(r"\.", str_)
print(str_1) # 结果:['.', '.']
(4)\d 匹配数字
规则:在正则匹配当中,大写和小写匹配的内容是相反的
import re
str_ = "zhe ge 20000 na ge 5000"
str_1 = re.findall(r"\d", str_) # 匹配一个数字
str_2 = re.findall(r"\d\d", str_) # 匹配连续两个数字
print(str_1) # 结果:['2', '0', '0', '0', '0', '5', '0', '0', '0']
print(str_2) # 结果:['20', '00', '50', '00']
(5)\D 匹配非数字
import re
str_ = "zhe $$ 20000 na **a5000"
str_1 = re.findall(r"\D", str_) # 匹配一个非数字
str_2 = re.findall(r"\D\D", str_) # 匹配连续两个非数字
print(str_1) # 结果:['z', 'h', 'e', ' ', '$', '$', ' ', ' ', 'n', 'a', ' ', '*', '*', 'a']
print(str_2) # 结果:['zh', 'e ', '$$', ' n', 'a ', '**']
(6)\w 匹配数字、字母,下划线
import re
str_ = "zhe $$ 20000 _na ** a_ 5000_"
str_1 = re.findall(r"\w", str_) # 匹配一个数字,字母,下划线
str_2 = re.findall(r"\w\w", str_) # 匹配两个数字,字母,下划线
print(str_1) # 结果:['z', 'h', 'e', '2', '0', '0', '0', '0', '_', 'n', 'a', 'a', '_', '5', '0', '0', '0', '_']
print(str_2) # 结果:['zh', '20', '00', '_n', 'a_', '50', '00']
(7)\W 匹配非数字、字母,下划线
import re
str_ = "zhe $$¥ 20000 _na ** a_ 5000_"
str_1 = re.findall(r"\W", str_) # 匹配一个非数字、字母,下划线
str_2 = re.findall(r"\W\W", str_) # 匹配两个非数字、字母,下划线
print(str_1) # 结果:[' ', '$', '$', '¥', ' ', ' ', ' ', '*', '*', ' ', ' ']
print(str_2) # 结果:[' $', '$¥', ' *', '* ']
(8)\s 匹配所有空格,但是包含\t,\n
import re
str_ = "suner\n yao hao hao xue xi\t"
str_1 = re.findall(r"\s", str_) # 按长度为1(包含\n\t)匹配空格
str_2 = re.findall(r"\s\s", str_) # 按长度为2(包含\n\t)匹配空格
print(str_1) # 结果:['\n', ' ', ' ', ' ', ' ', ' ', '\t']
print(str_2) # 结果:['\n ']
(9)\S 匹配所有非空格
import re
str_ = "suner\n you 200 %% *&¥\t"
str_1 = re.findall(r"\S", str_) # 按长度为1匹配非空格
str_2 = re.findall(r"\S\S", str_) # 按长度为2匹配非空格
print(str_1) # 结果:['s', 'u', 'n', 'e', 'r', 'y', 'o', 'u', '2', '0', '0', '%', '%', '*', '&', '¥']
print(str_2) # 结果:['su', 'ne', 'yo', '20', '%%', '*&']
(10)[] 匹配指定的任意一个元素
import re
str_ = "suner hao hao xue xi ya"
str_1 = re.findall(r"[e]", str_) # 匹配"e"
str_2 = re.findall(r"[a][o]", str_) # 匹配"ao"
str_3 = re.findall(r"[ao]", str_) # 匹配"a"或"o"
print(str_1) # 结果:['e', 'e']
print(str_2) # 结果:['ao', 'ao']
print(str_3) # 结果:['a', 'o', 'a', 'o', 'a']
(11)[-] 匹配指定范围里的任意一个元素
import re
str_ = "suner a 2y 1234589 "
str_1 = re.findall(r"[1-5]", str_) # 匹配1-5之间的
str_2 = re.findall(r"[a-f]", str_) # 匹配a-f之间的
str_3 = re.findall(r"[1-5][s-z]", str_) # 匹配第一个为1-5之间并且第二个为a-f之间的
print(str_1) # 结果:['2', '1', '2', '3', '4', '5']
print(str_2) # 结果:['e', 'a']
print(str_3) # 结果:['2y']
(12)[^] 对中括号当中的所有元素取非,取反
import re
str_ = "suner hao hao"
str_1 = re.findall(r"[^un]", str_) # 匹配非un的元素
str_2 = re.findall(r"[^un][^ao]", str_) # 匹配第一个为非un,第二个为非ao的元素
print(str_1) # 结果:['s', 'e', 'r', ' ', 'h', 'a', 'o', ' ', 'h', 'a', 'o']
print(str_2) # 结果:['su', 'er', ' h', 'o ']
(13)| 匹配符号两边任意一边
import re
str_ = "suner hao hao"
str_1 = re.findall(r"u|h", str_) # 匹配所有u或者h
print(str_1) # 结果:['u', 'h', 'h']
(14)^ 代表开头
import re
str_ = "suner hao hao"
str_1 = re.findall(r"^s", str_) # 匹配以"s"开头元素
str_2 = re.findall(r"^u", str_) # 匹配以"s"开头元素
print(str_1) # 结果:['s']
print(str_2) # 结果:[]
(15)$ 代表结尾
import re
str_ = "suner hao"
str_1 = re.findall(r"o$", str_) # 匹配以"o"结尾的
str_2 = re.findall(r"a$", str_) # 匹配以"a"开头元素
print(str_1) # 结果:['o']
print(str_2) # 结果:[]
(16)() 组匹配,会将组之外的内容作为匹配条件
import re
str_ = "su1 su1 ner hao 123 hao ** 8956 _5"
str_1 = re.findall(r"(\w\d)", str_) # 匹配数字、字母、下划线+数字
str_2 = re.findall(r"(\w\D)", str_) # 匹配数字、字母、下划线+非数字
str_3 = re.findall(r"(\w)\D", str_) # 匹配一个数,匹配的这个数后面接的是非数字
print(str_1) # 结果:['u1', 'u1', '12', '89', '56', '_5']
print(str_2) # 结果:['su', '1 ', 'su', '1 ', 'ne', 'r ', 'ha', 'o ', '3 ', 'ha', 'o ', '6 ']
print(str_3) # 结果:['s', '1', 's', '1', 'n', 'r', 'h', 'o', '3', 'h', 'o', '6']
(17)(?p<>) 命名分组
命名分组就是给具有默认分组编号的组另外再给一个别名
格式:(?P<name>正则表达式) # name是一个合法的标识符
2.对数量的描述
(1)* 0到多次
import re str_ = "sun 678 er" str_1 = re.findall(r"\d*", str_) # 匹配0次或者多次数字 str_2 = re.findall(r"\D*", str_) # 匹配0次或者多次非数字 print(str_1) # 结果:['', '', '', '', '678', '', '', '', ''] print(str_2) # 结果:['sun ', '', '', '', ' er', '']
(2)+ 1到多次
import re str_ = "sun 678 er" str_1 = re.findall(r"\d+", str_) # 匹配1次或者多次数字 str_2 = re.findall(r"\D+", str_) # 匹配1次或者多次非数字 print(str_1) # 结果:['678'] print(str_2) # 结果:['sun ', ' er']
(3)? 0到1次
import re str_ = "sun28541" str_1 = re.findall(r"\d?", str_) # 匹配0次或者1次数字 str_2 = re.findall(r"\D?", str_) # 匹配0次或者1次非数字 print(str_1) # 结果:['', '', '', '2', '8', '5', '4', '1', ''] print(str_2) # 结果:['s', 'u', 'n', '', '', '', '', '', '']
(4){} 匹配指定次
import re str_ = "sune28541" str_1 = re.findall(r"\d{2}", str_) # 匹配两个都是数字的元素 str_2 = re.findall(r"\D{1,3}", str_) # 匹配1个或3个非数字 print(str_1) # 结果:['28', '54'] print(str_2) # 结果:['sun', 'e']
3.特殊匹配
(1)贪婪匹配
import re # .* 贪婪匹配,如以第一个s开头最后一个r结尾,直至匹配到最后一个 # .*? 反贪婪匹配,如以第一个s开头第一个r结尾,即匹配到了就不匹配了 str_ = "suner285ner41ner" str_1 = re.findall(r"s(.*)r", str_) str_2 = re.findall(r"s(.*?)r", str_) print(str_1) # 结果:['uner285ner41ne'] print(str_2) # 结果:['une']
(2)re.I 忽略大小写匹配
import re str_ = "suneruNerUnerUN" str_1 = re.findall(r"un", str_) # 默认不忽略大小写 str_2 = re.findall(r"un", str_, re.I) # 设置忽略大小写 print(str_1) # 结果:['un'] print(str_2) # 结果:['un', 'uN', 'Un', 'UN']
(3)re.M 忽略换行(默认就是忽略换行,匹配所有字符)
import re str_ = "suner\nyao\nhao\nhao\nxue\nxi" str_1 = re.findall(r"ao", str_) # 默认 str_2 = re.findall(r"ao", str_, re.M) # 默认设置忽略换行 print(str_1) # 结果:['ao', 'ao', 'ao'] print(str_2) # 结果:['ao', 'ao', 'ao']
(4)re.S
如果不使用re.S参数,则只在每一行内进行匹配,如果一行没有,就换下一行重新开始,不会跨行。
使用re.S参数以后,正则表达式会将这个字符串作为一个整体,将“\n”当做一个普通的字符加入到这个字符串中,在整体中进行匹配。
import re str_ = """ suner hen nuli """ str_1 = re.findall(r"^.", str_) str_2 = re.findall(r"^.", str_, re.S) print(str_1) # 结果:[] print(str_2) # 结果:['\n']
4.匹配方法
Compile 匹配模板,这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象
import re # compile 匹配模板,先定义出匹配模板,在匹配字符 str_ = "suner 20190226" compile_num = re.compile(r"\d") # 定义匹配模板 str_1 = compile_num.findall(str_) # 进行匹配 compile_not_num = re.compile(r"\D") # 定义匹配模板 str_2 = compile_not_num.findall(str_) # 进行匹配 print(str_1) # 结果:['2', '0', '1', '9', '0', '2', '2', '6'] print(str_2) # 结果:['s', 'u', 'n', 'e', 'r', ' ']
(1)match匹配
从开头进行匹配,匹配一次,如果没有遇到,就返回None
import re str_ = "suner 20190226" str_1 = re.match(r"\d", str_) # 从开头匹配,没有就返回None str_2 = re.match(r"\w", str_) # 从开头匹配,有就返回匹配对象 print(str_1) # 结果:None print(str_2) # 结果:<_sre.SRE_Match object; span=(0, 1), match='s'> print(str_2.group()) # 结果:s ,取出匹配值用group()方法
(2)search匹配
从左往右进行匹配,匹配一次,如果没有遇到,就返回None
import re str_ = "suneur 20190226" str_1 = re.search(r"y", str_) # 从左往右匹配1次,没有就返回None str_2 = re.search(r"u", str_) # 从左往右匹配1次,有就返回匹配对象 print(str_1) # 结果:None print(str_2) # 结果:<_sre.SRE_Match object; span=(1, 2), match='u'> print(str_2.group()) # 结果:u
(3)split匹配
类似字符串的split
import re str_ = "sun2019 eun 23er 0226" str_1 = re.split(r"\d", str_) # 以数字分隔 str_2 = re.split(r"\D", str_) # 以非数字分隔 print(str_1) # 结果:['sun', '', '', '', ' eun ', '', 'er ', '', '', '', ''] print(str_2) # 结果:['', '', '', '2019', '', '', '', '', '23', '', '', '0226']
(4)sub匹配
类似字符串的replace
import re str_ = "sun2019 eun 23er 0226" str_1 = re.sub(r"\d", "8", str_) # str_中的所有数字替换为“8” str_2 = re.sub(r"\D", "s", str_) # str_中的所有非数字替换为“s” print(str_1) # 结果:sun8888 eun 88er 8888 print(str_2) # 结果:sss2019sssss23sss0226