python基础-第五篇-5.4正则表达式
正则基础知识
- 正则表达式是通过调用re模块实现的
- 在python里,正则表达式处理对象为字符串,所以正则里方法和字符串的方法有很多相似的地方:re.findall和find,re.split和split,re.sub和replace
- 普通字符和元字符
普通字符
大多数的字符和字母都为普通字符
元字符
在正则里,有其特殊的功能的字符称为元字符,如:. ^ $ * + ? {} | () \
- . 除了换行符任意一个字符进行匹配
import re
strs = 'ji154\n651jia*-'
m = re.findall('.',strs) #findall把所有匹配成功的对象装一个列表返回
print(m)
#结果为:['j', 'i', '1', '5', '4', '6', '5', '1', 'j', 'i', 'a', '*', '-']
- ^ 以什么开头
import re
strs = 'alex123'
m = re.search('^alex',strs) #匹配成功返回match对象,否则返回None
if m:
print(m.group()) #alex
- $ 以什么结尾
import re
strs = '123alex'
m = re.search('alex$',strs)
if m:
print(m.group()) #alex
- * 匹配0或多个,贪婪匹配的字符
import re
str1 = 'alexxxxx'
str2 = 'alex'
str3 = 'ale'
m1 = re.match('alex*',str1) #match从头匹配,匹配成功返回match对象,否则返回None
if m1:
print(m1.group()) #alexxxxx
m2 = re.match('alex*',str2)
if m2:
print(m2.group()) #alex
m3 = re.match('alex*',str3)
if m3:
print(m3.group()) #ale
- + 匹配一个或多个,也是贪婪匹配
import re
str1 = 'alexxxxx'
str2 = 'alex'
str3 = 'ale'
m1 = re.match('alex+',str1)
if m1:
print(m1.group()) #alexxxxx
m2 = re.match('alex+',str2)
if m2:
print(m2.group()) #alex
m3 = re.match('alex+',str3)
if m3: #条件不成立
print(m3.group())
print(m3) #None
- ? 匹配0或1个
import re
str1 = 'alexxxx'
str2 = 'alex'
str3 = 'ale'
m1 = re.match('alex?',str1)
if m1:
print(m1.group()) #alex
m2 = re.match('alex?',str2)
if m2:
print(m2.group()) #alex
m3 = re.match('alex?',str3)
if m3:
print(m3.group()) #ale
- {} 规定匹配的个数或范围,范围是开区间,也就是说能取到上界
import re
str1 = 'alexxx'
str2 = 'alexxxxx'
m1 = re.search('alex{3}',str1)
if m1:
print(m1.group()) #alexxx
m2 = re.search('alex{3,5}',str1)
if m2:
print(m2.group()) #alexxx
m3 = re.search('alex{3,5}',str2)
if m3:
print(m3.group()) #alexxxxx
- [] 字符集,匹配过程中字符集的字符是或的关系,而且一个集就匹配一个字符
import re
str1 = 'jing264-*4*df'
m1 = re.search('[a-z]',str1) #search从左往右匹配,匹配成功就不再往后匹配
if m1:
print(m1.group()) #j
m2 = re.findall('[a-z]',str1)
print(m2) #['j', 'i', 'n', 'g', 'd', 'f']
元字符在字符集中会失去其特有功能,回归本性,除-,^,\
import re
m = re.findall('[^1-9]','ww32sd8l') #在字符集里,^表示非,在这里就是非数字
print(m) #['w', 'w', 's', 'd', 'l']
import re
m = re.findall('[*\^]','kdf*nd15^1j5') #匹配星号或折号
print(m) #['*', '^']
- () 组,如同在算式中小括号,具有优先权
import re
m = re.findall('(ab)+','abababab156712') #findall对组有优先获取权
print(m) #['ab']
m2 = re.search('(ab)+','abababab156712')
if m2:
print(m2.group()) #abababab
- | 或
import re
m = re.findall('(abc)|(1)|(\n)','jicabc21\n1')
print(m) #[('abc', '', ''), ('', '1', ''), ('', '', '\n'), ('', '1', '')]
m = re.findall('(\d)+','abcabc21ji')
print(m) #['1']
m = re.findall('(abc)','jicabc21\n1',re.M)
print(m) #['abc']
\ 反斜杠后边跟元字符去除特殊功能:
正则的\与python里的\--当正则规则与python规则相冲突时
#匹配字符里的\
import re
m = re.findall('\\\\','abc\com')
print(m) #['\\']
m2 = re.findall(r'\\','abc\com')
print(m2) #['\\']


你会不会觉得就因为正则规则和python规则相冲突而把这个搞得好麻烦呢??所以r登场了,它是让python别胡乱瞎搞的
反斜杠后跟普通字符实现特殊功能
- \d 数字--相当[0-9]
- \D 非数字--相当[^0-9]
- \w 匹配任何字母数字字符--相当[a-zA-Z0-9]
- \W 匹配任何非字母数字字符--相当[^a-zA-Z0-9]
- \s 匹配任何空白字符--相当[ \t\n\r\f\v]
- \S 匹配任何非空白字符--相当[^ \t\n\r\f\v]
- \b 匹配一个单词边界,也就是单词和空格间的位置(特殊字符也适用)
import re
str1 = '4d4g2c\n 5\v'
m1 = re.findall('\d',str1)
print(m1) #['4', '4', '2', '5']
m2 = re.findall('\w',str1)
print(m2) #['4', 'd', '4', 'g', '2', 'c', '5']
m3 = re.findall('\s',str1)
print(m3) #['\n', ' ', '\x0b']
import re str1 = 'alex*eric eva' m4 = re.findall(r'\b',str1) print(m4) #['', '', '', '', '', '']
引用序号对应的字符组所匹配的字符串
import re
m = re.search(r'(alex)(eric)com\2\1','alexericcomericalex')
if m:
print(m.group()) #alexericcomericalex
非贪婪模式化
import re
m1 = re.search('a(\d+?)','a21471')
if m1:
print(m1.group()) #a2
m2 = re.search('a(\d*?)','a21471')
if m2:
print(m2.group()) #a
#如果前后有限定条件,再加非贪婪?--无效
m3 = re.search('a(\d+?)b','a265532b')
if m3:
print(m3.group()) #a265532b
m4 = re.search('a(\d+)b','a265532b')
if m4:
print(m4.group()) #a265532b
正则常见方法
-
re.match 从头匹配,一旦匹配成功,返回一个match对象
import re
#无分组
origin = 'hello alex bcd alex lge alex ccd 16'
r = re.match('h\w+',origin)
print(r.group()) #hello
print(r.groups()) #()--获取模型中匹配到的分组结果--等同于对匹配到的结果再次进行筛选
print(r.groupdict()) #{}--获取模型中匹配到的分组中所有执行了key的组
#有分组
r = re.match('(?P<n1>h)(\w+)',origin) #key对应的?P 大写p
print(r.group()) #hello
print(r.groups()) #('h', 'ello')--获取模型中匹配到的分组结果--等同于对匹配到的结果再次进行筛选
print(r.groupdict()) #{'n1': 'h'}--获取模型中匹配到的分组中所有执行了key的组
-
而对象有自己的group等方法
- group 返回被re匹配的的字符串,参数0或不写--默认匹配所有,1--匹配1组,2--匹配2组,3--匹配3组
- start 返回匹配开始的位置
- end 返回匹配结束的位置
- span 返回一个元组包含(开始,结束)的位置
import re
m1 = re.match('(a)(l)(e)(x)','alex')
print(m1.group(0)) #alex
print(m1.group(1)) #a
print(m1.group(4)) #x
print(m1.start()) #0
print(m1.end()) #4
print(m1.span()) #(0, 4)
-
第三参数--标志位(match和search差不多)
- re.I 使匹配对大小写不敏感
- re.S 使.匹配包括换行符在内的所有字符
- re.M 支持匹配多行
import re
# m1 = re.search('alex','ALEX',re.I)
# print(m1.group())
# m2 = re.findall('.','1d5\n2d',re.S)
# print(m2)
str1 = '123alex\nalex154ip\nalex15ip'
m3 = re.findall('^alex',str1,re.M)
print(m3) #以行头为头,以行尾为尾,进行^和$匹配
-
re.findall 匹配所有符合匹配模式的字符,以列表返回,如果遇组,优先捕获组的内容
-
re.finditer 匹配所有符合匹配模式的字符,返回迭代器
import re
n = re.findall('\d+\w\d+','a2b3c4d5')
print(n) #['2b3', '4d5']--你可能会想:怎么没有‘3c4’
#因为是顺序匹配,在没匹配成功的前提下,逐个往后找,所以结果里没有‘3c4’
#一旦匹配成功,等同拿走匹配到的字符串在往下匹配
import re
origin = 'hello alex bcd'
r = re.findall('(a)(\w+)(x)',origin)
print(r) #[('a', 'le', 'x')]
r2 = re.findall('(a)(\w+(e))(?P<n1>x)',origin)
print(r2) #[('a', 'le', 'e', 'x')] #findall方法里加key是无意义的,因为返回对象是列表,没有groupdict方法
import re
m1 = re.findall('a(le)x','alexjijfalexjijhfalex')
print(m1) #['le', 'le', 'le']
#破了findall的优先捕获组的权限--?:
m2 = re.findall('www.(?:baidu|laonanhai).com','jfswww.laonanhai.com')
print(m2) #['www.laonanhai.com']
import re
origin = 'hello alex bcd'
r = re.finditer('(a)(\w+)(e)(?P<n1>x)',origin)
print(r) #match对象组成的迭代器
for i in r:
print(i) #<_sre.SRE_Match object; span=(6, 10), match='alex'>
print(i.group()) #alex
print(i.groups()) #('a', 'l', 'e', 'x')
print(i.groupdict()) #{'n1': 'x'}
import re
a = 'alex'
n = re.findall('(\w)(\w)(\w)(\w)',a)
print(n) #[('a', 'l', 'e', 'x')]
n2 = re.findall('(\w){4}',a)
print(n2) #['x']
n3 = re.findall('(\w)*',a)
print(n3) #['x', ''] *最后会匹配一次空
import re
p = re.compile(r'\d+')
w = p.finditer('12 drwn44ers drumming,11alex10eric')
print(w)
for mat in w:
print(mat.group(),mat.span())
结果为:
<callable_iterator object at 0x0000000000D1FC50>
12 (0, 2)
44 (7, 9)
11 (22, 24)
10 (28, 30)
-
re.search 逐个往后找,匹配到一个,不再匹配,匹配成功返回一个match对象,没有匹配到就返回None
import re
m = re.search('alex','abalexsalex')
print(m)
if m:
print(m.group()) #alex
-
re.sub(’匹配模式‘,’新的‘,’旧的‘,’次数‘)
-
re.subn--自动计算替换次数
import re
m = re.sub('\d','love','i1you2you',1)
print(m) #iloveyou2you
m2 = re.subn('\d','love','1df4d17g4d8t12df')
print(m2) #('lovedflovedloveloveglovedlovetlovelovedf', 8)
-
re.compile 把正则表达式编译成一个正则表达式对象,当要对同一个正则规则使用多次时,建议用这种方式
import re
regex = re.compile(r'\w*oo\w*')
print(regex.findall('jisf4oo12df14')) #['jisf4oo12df14']
-
re.split 以匹配模式匹配到的字符串一个一个分割,如果匹配模式里有组,还会返回匹配上组的内容,第三参数为分割次数
import re
m = re.split('alex','jifalex15jialexdf7')
print(m) #['jif', '15ji', 'df7']
m = re.split('(alex)','jifalex15jialexdf7')
print(m) #['jif', 'alex', '15ji', 'alex', 'df7']
欢迎大家对我的博客内容提出质疑和提问!谢谢
笔者:拍省先生

浙公网安备 33010602011771号