Python 正则表达式
「正则表达式」
一 简介:
正则表达式,是一个特殊的字符序列,又称规则表达式(英语:Regular Expression,在代码中常简写为regex、regexp 或RE),本质而言是一种小型的,高度专业化的编程语言,在(Python)中它内嵌在Python中,并通过RE模块实现;能帮你方便的检查一个字符串是否与某种模式(规则)匹配。
正则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本;正则表达式模式被编译成一系列的字节码,然后用C编写的匹配引擎执行。
Python 自1.5版本起增加了re 模块,re 模块使Python语言拥有全部的正则表达式功能。
使用正则表达式进行匹配的流程:
# 导入re正则模块 import re
二 字符匹配:
正则表达式涉及到的字符,分为普通字符和元字符;元字符是具有特殊功能的字符。
1.普通字符: 大多数字符和字母都可以看作是普通字符。
#实例: >>> re.findall('jesson',"dsjkdfjsWRFDd jessonFFEEGsddeed') # 这里调用了方法re.findall() 该方法的主要功能是,符合条件的结果全部匹配;下文会单独介绍。 >>>['jesson'] #完全匹配 这里基本没有用到正则
2. 元字符:(11个)
. ^ $ * + ? {} [] \ | ()
(1)元字符“.” 通配符,可以代指所有字符,除了换行符号"\n",一个点,对应一个字符
#实例1: ret = re.findall('w...d','hello world') print(ret) #实例2: ret = re.findall('w...d','hello wor\nd') # 不能匹配“\n” print(ret) # 输出结果为空[],说明"."匹配不到"\n"
(2)元字符“^” 从整个字符串开头的地方匹配
#实例: ret = re.findall('^h...o','hello world') print(ret) #输出结果:['hello']
(3)元字符“$” 从整个字符串的结尾开始匹配。 可以理解成:从后往前匹配
#实例1: ret = re.findall('h...o$','hello world awdx') print(ret) # 输出结果为空 从整个字符的结尾,不是hello的结尾 #实例2: ret = re.findall('a..x$','hello world awdx') print(ret) #输出结果:['awdx'] 匹配成功
(4)元字符“*” 重复匹配 (表达式中的*表示重复*号前边字符 个数从0到正无穷)
#实例1:想匹配的 以a开头,以li 结尾的字符 #普通写法: ret = re.findall('a........li','hello world alex88888li') print(ret) # 输出结果:['alex88888li'] #采用“*”来写: ret = re.findall('a.*li','hello world alex88888li') print(ret) # 输出结果:['alex88888li'] #实例2: ret = re.findall('ba*','sjfjslafjbaaaaaaaaaaaa') print(ret) # 输出结果:['baaaaaaaaaaaa']
ret = re.findall('f*','hellof')
print(ret) # 输出结果:['', '', '', '', '', 'f', '']
ret = re.findall('f*','hello')
print(ret) # 输出结果:['', '', '', '', '', '']
# 表示取*前边的f,如果有f,可以匹配出,但是,注意没有f的情况下,也会匹配,结果为none值
(5)元字符"+" 表示匹配“+”前边的字符 个数从1到正无穷都能匹配
#实例1: ret = re.findall('ab+','dsljfsfjslfaaa') print(ret) # 输出结果为空 [] 说明没有找到字符b ret = re.findall('ab+','dsljfsfjslfaaabbbbbbbbbbb') print(ret) # 输出结果:['abbbbbbbbbbb'] #实例2: ret = re.findall('a+b','adadfwdbaaaaaablkls;flsabb') print(ret) # 输出结果:['aaaaaab', 'ab'] ret = re.findall('f+','hellof') print(ret) # 输出结果:['f'] ret = re.findall('f+','fhello') print(ret) # 输出结果:['f'] ret = re.findall('f+','hello') print(ret) # 输出结果:[] # 上述实例说明:取+前边的f 个数,如果有f 则匹配出,如果没有f,匹配结果为空,对比*
(6)元字符"?" 表示匹配"?"前边的字符 个数为闭区间[0,1] 即:0个或者1个
#实例: ret = re.findall('a?b','aaaabkshkgabsdbannndbab') print(ret) # 输出结果:['ab', 'ab', 'b', 'b', 'ab']
(7)元字符"{}" 表示匹配"{}"前边的字符 指定个数为"{}"里边的数值
#实例1: ret = re.findall('a{5}b','aaaaab') #匹配字符a 并且指定个数为5 即:表示匹配连续的5个a加上b print(ret) # 输出结果:['aaaaab'] #实例2: ret = re.findall('a{}b','aaaaab') # 如果中括号里边不加任何值 则表示{} 按照普通字符来匹配。 print(ret) # 输出结果为空[] 因为字符串'aaaaab'中没有"{}",将字符串'aaaaab'改成'aaaaa{}b' 就可以匹配到了。 #实例3: ret = re.findall('a{1,3}b','jksjablskflskaabdlsfaaaaab') # 大括号里边可以加参数{1,3}表示字符个数的范围。 print(ret) # 输出结果:['ab', 'aab', 'aaab'] #实例4: ret = re.findall('a{1,3}b','dlsfaaaaab') # 如果目标匹配对象中,只有一个 个数大于等于3的字符串 那么默认匹配显示最多;即:aab 而不是ab 或者 abb [贪婪匹配] print(ret) # 输出结果:['aaab']
(8)元字符"[]" 表示一个字符集,它常被用来指定一个字符类别,所谓字符类别就是你想匹配的一个字符集。字符可以单个列出,也可以用“-”号分隔的两个给定字符来表示一个字符区间。例如:[abc]将匹配"a","b",或者"c"中的任意一个字符;也可以用区间[a-c]来表示同一个字符集,和前者效果一致。如果只想匹配小写字符则可以写成[a-z]。
#实例1: ret = re.findall('a[c,d,e]x','adx') # []里边的内容 表示或者的关系 也就是说只要出现任意中括号中的内容 就会匹配。 print(ret) #实例2: ret = re.findall('[1-9,a-z,A-Z]','123jskdjJWKJKJKS') # ret = re.findall('[1-9a-zA-Z]','123jskdjJWKJKJKS') # 输出结果和上边的相同 只是解释器判断的逻辑顺序不同 print(ret) # 输出结果:['1', '2', '3', 'j', 's', 'k', 'd', 'j', 'J', 'W', 'K', 'J', 'K', 'J', 'K', 'S'] #实例3: "^" 尖角号放在中括号中 表示:除了XXX字符 即:非 ret = re.findall('[^4,5]','flja4slfj5') # 表示非4 或则 非5 print(ret) # 输出结果:['f', 'l', 'j', 'a', 's', 'l', 'f', 'j']
(9)元字符"\" 反斜杠
反斜杠后边跟元字符,去除其特殊功能反斜杠
反斜杠后边跟普通字符,实现其特殊功能
\d #表示:匹配任何十进制数,它相当于[0-9] \D #表示:匹配任何 非 数字字符,它相当于[^0-9] \s #表示:匹配任何空白字符,它相当于[\t\n\r\f\v] \S #表示:匹配任何 非 空白字符,它相当于[^\t\n\r\f\v] \w #表示:匹配任何字母数字字符,它相当于[a-zA-Z0-9] \W #表示:匹配任何 非 字母数字字符,它相当于[^a-zA-Z0-9] \b #表示:匹配一个单词边界,即:匹配字符和空格间的位置
#实例: print(re.findall('\w','fada sess')) print(re.findall('\W','fada sess')) # 匹配任何 非 字母数字字符 这里相当于“空格” print(re.findall('a\b','fada sess')) # print(re.findall(r'a\b','fada sess')) # 加r表示 原生字符串读取
(10)元字符"()" 表示:分组 将括号中的内容 当作整体来对待
#实例1: print(re.findall('(as)','ksjdksjasas')) print(re.findall('(as)+','ksjdksjasas')) print(re.search('(as)','ksjdksjasas').group()) print(re.search('(as)+','ksjdksjasas').group()) # 输出结果对比: # ['as', 'as'] # ['as'] # as # asas #实例2: print(re.search('(as)','ksjdksjasas').group()) print(re.search('(as)|222','ksjdksjasas222').group()) # | 管道符表示或者 # 输出结果:相同 因为管道符前边的匹配成功后,后边的条件“222”就不会去匹配。 # as # as #实例3: ret = re.search('(?P<id>\d{3})/(?P<name>\w{6})','skejksd001/jessonadf002/pitterxd') print(ret.group()) print(ret.group('id')) # group('')添加组成员参数 print(ret.group('name')) # 输出结果: # 001/jesson # 001 # jesson #.findall() 对比上方的 .search() ret = re.findall('(?P<id>\d{3})/(?P<name>\w{6})','skejksd001/jessonadf002/pitterxd') print(ret) # 输出结果: #[('001', 'jesson'), ('002', 'pitter')]
(11)元字符"|" 管道符 表示逻辑:或者
print(re.search('(as)|222','ksjdksjasas222').group()) print(re.findall('(as)|222','jasas222'))
元字符功能总结:
"." 通配符,匹配任意单个字符,默认不会匹配\n换行符,加re.S可以实现匹配换行符 "^" 从整个字符串开头的地方匹配 "$" 从整个字符串的结尾开始匹配 即:从后往前匹配 "*" 重复匹配 (表示匹配重复的*号前边字符 个数从0到正无穷) "+" 匹配“+”前边的字符 个数从1到正无穷都能匹配 "?" 匹配"?"前边的字符 个数为闭区间[0,1] 即:0个或者1个 "{}" 匹配"{}"前边的字符 指定个数为"{}"里边的数值 "[]" 表示一个字符集,常被用来指定匹配一个字符类别 例如:[0-9,a-z,A-Z] "\" 反斜杠 后边跟元字符,去除其特殊功能;后边跟普通字符,实现其特殊功能 "()" 表示:分组 将括号中的内容 当作整体来对待 "|" 管道符 表示逻辑:或者 常常配合分组使用;例如:print(re.findall('(as)|222','jasas222'))
三 方法
(1) 方法:findall() (即:全部找到,返回的是一个列表)
#实例: s = 'hello world' ret = re.findall('w\w{3}d','hello world') print(ret)
(2) 方法:search() (即:匹配出第一个满足条件的结果,返回的是一个对象) 可以通过调用.group()方法,可以将匹配的结果输出。
#实例: ret = re.search('h..','hello hello world') print(ret) # 输出结果:<_sre.SRE_Match object; span=(0, 3), match='hel'> ret1 = re.search('h..','hello hello world').group() print(ret1) # 输出结果:hel 只输出第一个符合条件的结果
(3)方法:match() 返回匹配到的第一个对象,只在字符串开始匹配。同样,可以通过调用.group()方法,可以将匹配的结果输出。
#注意: # match() 只检测RE是不是在string的开始位置匹配, # search() 会扫描整个string查找匹配; # 也就是说match() 只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none
#实例: ret = re.match('asd','asdhskdjfksji') print(ret) # 输出结果:<_sre.SRE_Match object; span=(0, 3), match='asd'>返回的是一个对象。 ret1 = re.match('asd','asdhskdjfasdksjiasd').group() print(ret1) # 输出结果:asd 调用.group()方法,只返回匹配的第一个结果。
(4)方法:split() 分隔符 对比字符串里边的split方法。
实例1: ret = re.split('j','dsdhsjdwakjdswddkdjsjwkjd') print(ret) # 输出结果:['dsdhsjd', 'jds', 'jd'] 以k为分隔符,将字符分隔,返回结果。 实例2: ret1 = re.split('[j,k]','dsdhsjdwakjdswddkdjsjwkjd') print(ret1) # 输出结果: ['dsdhs', 'dwak', 'dswddkd', 's', 'wk', 'd'] ['dsdhs', 'dwak', 'dswddkd', 's', 'wk', 'd'] ['dsdhs', 'dwa', '', 'dswdd', 'd', 's', 'w', '', 'd'] # 对比上方的两个输出结果,可以发现:匹配的执行顺序是,先以中括号中的第一个规则字符“j”进行匹配, # 然后,在分隔结果的基础上,再以第二个规则字符“k”,对其进行分隔。匹配结果中单独的字符"k" 被分隔后,输出空''
(5)方法: sub() 替换;类似字符串中的replace()方法。
ret = re.sub('a..x','jesson','hello,alex') print(ret) # 输出结果:hello,jesson
(6)方法: compile(strPattern[,flag]): 这个方法是Pattern类的工厂方法,用于将字符串形式的正则表达式编译为Pattern对象。第二个参数flag是匹配模式,取值可以使用 按位 或 运算符“|” 表示同时生效。
简单来说,该方法的功能就是:可以把正则表达式编译成一个正则表达式对象。一定程度,可以提高效率。
#实例: # 未采用compile()方法: ret = re.findall('\.com','www.baidu.com___www.jingdong.com') print("ret",ret) # 采用compile()方法: obj = re.compile('\.com') ret1 = obj.findall('www.baidu.com___www.jingdong.com') print("ret1",ret1) # 两次输出结果:相同 # ret ['.com', '.com'] # ret1 ['.com', '.com']