正则表达式
是匹配字符串内容的一种规则,可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串中取出符合某个条件的子串等。
正则表达式是由普通字符(例如字符 a 到 z)以及特殊字符(称为"元字符")组成的文字模式。模式描述在搜索文本时要匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
元字符
. |
匹配除换行符以外的任意字符 |
\w |
匹配字母或数字或下划线 |
\s |
匹配任意的空白符 |
\d |
匹配数字 |
\n |
匹配一个换行符 |
\t |
匹配一个制表符 |
\b |
匹配一个单词的结尾 |
^ |
匹配字符串的开始 |
$ |
匹配字符串的结尾 |
\W(大写) |
匹配非字母或数字或下划线
|
\D(大写) |
匹配非数字
|
\S(大写) |
匹配非空白符
|
a|b |
匹配字符a或字符b
|
() |
匹配括号内的表达式,也表示一个组
|
[...] |
匹配字符组中的字符
|
[^...] |
匹配除了字符组中字符的所有字符
|
\r |
匹配一个回车符
|
\f |
匹配一个换页符
|
量词
请注意,限定符出现在范围表达式之后。因此,它应用于整个范围表达式
量词 |
用法说明 |
* | 重复零次或更多次 |
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
*、+限定符都是贪婪的,因为它们会尽可能多的匹配文字,只有在它们的后面加上一个?就可以实现非贪婪或最小匹配。
*? 重复任意次,但尽可能少重复 +? 重复1次或更多次,但尽可能少重复 ?? 重复0次或1次,但尽可能少重复 {n,m}? 重复n到m次,但尽可能少重复 {n,}? 重复n次以上,但尽可能少重复
例如: .*?的用法
. 是任意字符 * 是取 0 至 无限长度 ? 是非贪婪模式。 合在一起就是 取尽量少的任意字符,一般不会这么单独写,他大多用在: .*?x 就是取前面任意长度的字符,直到一个x出现
字符组:[ ] 在同一位置可能出现的各种字符组成一个字符组。字符可以是数字、字母或者下划线。需要从小到大依次排列 。
注:字符组只输出一个字符,它是一个范围
例如:[0-9] :0到9内的一个数字
[A-a]:A到a内的一个字符,根据ascii
[0-9x]: 0到9内的一个数字 以及x
转义符
在正则表达式中,有很多有特殊意义的是元字符,比如\d和\s等,如果要在正则中匹配正常的"\d"而不是"数字"就需要对"\"进行转义,变成'\\'。
在python中,无论是正则表达式,还是待匹配的内容,都是以字符串的形式出现的,在字符串中\也有特殊的含义,本身还需要转义。所以如果匹配一次"\d",字符串中要写成'\\d',那么正则里就要写成"\\\\d",这样就太麻烦了。这个时候我们就用到了r'\d'这个概念,此时的正则是r'\\d'就可以了。
正则 | 待匹配字符 | 匹配 结果 |
说明 |
\d | \d | False |
因为在正则表达式中\是有特殊意义的字符,所以要匹配\d本身,用表达式\d无法匹配 |
\\d | \d | True |
转义\之后变成\\,即可匹配 |
"\\\\d" | '\\d' | True |
如果在python中,字符串中的'\'也需要转义,所以每一个字符串'\'又需要转义一次 |
r'\\d' | r'\d' | True |
在字符串之前加r,让整个字符串不转义 |
re模块下的常用方法
import re #导入re模块
findall:re.findall遍历匹配,可以获取字符串中所有匹配的字符串,返回一个列表。
格式:re.findall(pattern, string, flags=0)
ret = re.findall('e', 'hello everyone') # 返回所有满足匹配条件的结果,放在列表里
print(ret) #结果 : ['e', 'e','e','e']
search:re.search函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回,如果字符串没有匹配,则返回None。
re.search(pattern, string, flags=0)
ret = re.search('e', 'hello everyone').group()
print(ret) #结果 : 'e' # 通过调用group()方法得到匹配的字符串,如果字符串没有匹配,则返回None。
match:决定RE是否在字符串刚开始的位置匹配。
注:这个方法并不是完全匹配。当pattern结束时若string还有剩余字符,仍然视为成功。想要完全匹配,可以在表达式末尾加上边界匹配符'$'
格式 re.match(pattern, string, flags=0) pattern表示正则表达式,string表示要匹配的字符串
ret = re.match('e', 'hello everyone').group() # 和search一样,不过是在字符串开始处进行匹配
print(ret) #结果 : 'e'
split:按照能够匹配的子串将string分割后返回列表
格式:
re.split(pattern, string[, maxsplit])
maxsplit用于指定最大分割次数,不指定将全部分割ret = re.split('[ab]', 'abcd') # 先按'a'分割得到''和'bcd',在对''和'bcd'分别按'b'分割 print(ret) # ['', '', 'cd']
sub:使用re替换string中匹配的子串后返回替换后的字符串
格式:re.sub(pattern, repl, string, count) repl表示用什么替换,count表示替换的个数
ret = re.sub('\d', 'H', '1ello world', 1)#将数字替换成'H',参数1表示只替换1个 print(ret) #hello world
subn:返回替换次数 ret = re.subn('\d', 'H', '1ello world 1')#将数字替换成'H',返回元组(替换的结果,替换了多少次) print(ret)
compile:编译正则表达式对象
obj = re.compile('\d{3}') #将正则表达式编译成为一个 正则表达式对象,规则要匹配的是3个数字
ret = obj.search('abc123eeee') #正则表达式对象调用search,参数为待匹配的字符串
print(ret.group()) #结果 : 123
finditer:搜索string,返回一个顺序访问每一个匹配结果(Match对象)的迭代器。
找到 RE 匹配的所有子串,并把它们作为一个迭代器返回。
格式:re.finditer(pattern, string, flags=0)
import re ret = re.finditer('\d', 'ds3sy4784a') #finditer返回一个存放匹配结果的迭代器 print(ret) # <callable_iterator object at 0x10195f940> 得到可被调用的迭代器 print(next(ret).group()) #查看第一个结果 print(next(ret).group()) #查看第二个结果 print([i.group() for i in ret]) #查看剩余的左右结果
组()
()在findall的优先级查询
import re ret = re.findall('123(ABC)', '123ABC456') print(ret) # ['ABC'] 这是因为findall会优先把匹配结果组里内容返回,如果想要匹配结果,取消权限即可 ret = re.findall('123(?:ABC)', '123ABC456') #在括号内加入 ?: 就可以取消权限
print(ret) # ['123(ABC)']
()在split的应用
# import re # f=re.split('\d','what1are2you3doing') # print(f)
['what', 'are', 'you', 'doing']
# import re
# f=re.split(('\d'),'what1are2you3doing')
# print(f)
['what', '1', 'are', '2', 'you', '3', 'doing'] #当正则表达式加上括号时,被匹配的项被保留了下来
import re ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>","<h1>hello</h1>")
print(ret.group('tag_name')) #结果 :h1
print(ret.group(1)) #结果 :h1 print(ret.group()) #结果 :<h1>hello</h1>
#这里正则表达式和带匹配的字符串时一一对应的
#还可以在分组中利用 ?p<name> 的形式给分组起名字
#获取的匹配结果可以直接用group('名字')拿到对应的值.
#当然也可以根据括号的序号来进行求值,序号从左到右数,从1开始