元字符: . ^ $ * + ? { } [ ] | () \
1、. 通配符 匹配除换行符(\n、\r)之外的任何单个字符。
import re
s = 'hello world wdfl hedl wwwl'
ret = re.findall('w..l',s) #.只能代指任意一个字符,不能匹配\n(换行符)
print(ret)
# 输出: ['worl', 'wdfl', 'wwwl']
2、^ 匹配输入字符串的开始位置。
import re
s = 'hello world wdfl hedl wwwl'
ret = re.findall('^w..l',s) #.只能代指任意一个字符,不能匹配\n(换行符)
print(ret)
#输出:[]
import re
s = 'world wdfl hedl wwwl'
ret = re.findall('^w..l',s) #.只能代指任意一个字符,不能匹配\n(换行符)
print(ret)
# 输出: ['worl']
# 结论:^匹配最开始的位置
3、$ 匹配输入字符串的结束位置。
import re
s = 'world wdfl hedl wwwl asdf'
ret = re.findall('w..l$',s) #.只能代指任意一个字符,不能匹配\n(换行符)
print(ret)
#输出:[]
s = 'world wdfl hedl wwwl'
ret = re.findall('w..l$',s) #.只能代指任意一个字符,不能匹配\n(换行符)
print(ret)
#输出:['wwwl']
#结论 只匹配结尾
4、*:重复匹配(0-无穷大)
import re
s = 'world wdfl hedl wwwl'
ret = re.findall('w.*l',s) # *代表前面的字符,这里指.
print(ret)
#输出:['world wdfl hedl wwwl']
s = 'abbbgdhssdkkhjabbbbbbgjhhjkk ag'
ret = re.findall('ab*g',s) # *代表前面的字符,这里指b 也可以没有b,如ag
print(ret)
#输出:['abbbg', 'abbbbbbg', 'ag']
#结论*代表重复前面的字符匹配
5、+ 匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
示例:
import re
s = 'waa waaaa '
ret = re.findall('wa+',s) #
print(ret)
#输出:['waa', 'waaaa']
s = 'waab waaaa '
ret = re.findall('w.+b',s) #
print(ret)
#输出: ['waab']
s = 'waab wb '
ret1 = re.findall('wa+b',s) # + 匹配前面的字符1次或多次不能为0次
ret2 = re.findall('wa*b',s) # * 匹配前面的字符0次或多次可以为0次
print(ret1)
print(ret2)
#输出:
['waab']
['waab', 'wb']
6、? 匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 。? 等价于 {0,1}。
示例:
import re
s = 'waab wab wb'
ret = re.findall('wa?b',s) #
print(ret)
#输出:['wab', 'wb']
#结论:?只能匹配前面的字符0次或一次
7、{n} {n,} {n,m}
示例:
import re
#{n}
ret = re.findall('fa{2}b','fab faab faaaab') #2代表匹配两个a
print(ret)
# 输出:['faab']
# 结论: n 是一个非负整数。匹配确定的 n 次。例如,'a{2}b' 不能匹配 "fab" 中的 'a',但是能匹配 "faab" 中的两个 a
#{n,}
ret = re.findall('fa{2,}b','fab faab faaaab ')
print(ret)
#输出:['faab', 'faaaab'] 最少匹配n个a,这里最少匹配2个
#结论:n 是一个非负整数。至少匹配n 次。例如,'a{2,}' 不能匹配 "fab" 中的 'a',但能匹配 "faaaaab" 中的所有 a。'a{1,}' 等价于 'a+'。'a{0,}' 则等价于 'o*'。
#{n,m} n<=m
ret = re.findall('fa{2,5}b','fb fab faab faaab faaaab faaaaab faaaaaab')
print(ret)
#输出:['faab', 'faaab', 'faaaab', 'faaaaab'] 可以匹配n到m个字符
#结论:m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"a{1,3}" 将匹配 "faaaaad" 中的前三个 a。'a{0,1}' 等价于 'a?'。请注意在逗号和两个数之间不能有空格。
8、()将()的内容作为一个整体来进行匹配
示例:
# -------------------------() |------------------------------------
# 将()的内容作为一个整体来进行匹配
s = 'My phone number is 012-239-4597 022-249-4597 332-249-4598'
m=re.search(r'(\d{3})-(\d{3}-\d{4})',s[0:31])
print('m.group(1): ', m.group(1)) # 传入参数1 打印第一组数据 012
print('m.group(2): ', m.group(2)) # 传入参数2 打印第二组数据 239-4597
print('m.group(): ', m.group()) # 默认都打印 012-239-4597
print('m.start(): ', m.start()) # 返回指定的组截获的子串在string中的起始索引(子串第一个字符的索引)。group默认值为0。 19
print('m.end(): ', m.end()) # 返回指定的组截获的子串在string中的结束索引(子串最后一个字符的索引+1)。group默认值为0。 31
print('m.span(: ', m.span()) # 返回(start(group), end(group))。
print('m.pos: ', m.pos) # 文本中正则表达式开始搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
print('m.endpos: ', m.endpos) # 文本中正则表达式结束搜索的索引。值与Pattern.match()和Pattern.seach()方法的同名参数相同。
print('m.lastindex: ', m.lastindex) #最后一个被捕获的分组在文本中的索引。如果没有被捕获的分组,将为None。
print('m.lastgroup: ', m.lastgroup) #最后一个被捕获的分组的别名。如果这个分组没有别名或者没有被捕获的分组,将为None。
m=re.search(r'(\d{3})-(\d{3}-\d{4})',s[m.endpos:])
print('m.group(): ', m.group())
m=re.search(r'(\d{3})-(\d{3}-\d{4})',s)
area_code,manin_cod = m.groups()
print('m.groups(): ', m.groups())
print('m.group(): ', m.group())
print('area_code: ', area_code)
print('manin_cod: ', manin_cod)
#-------------(?P<name>...)--命名组,通过组的名字(name)即可访问到子组匹配的字符串
ss = 'My name is zhang age 26'
person = re.search('(?P<name>\w{5}) \w{3} (?P<age>\d{2})', ss)
print('My name is:', person.group('name'))
print('My age is:', person.group('age'))
注:后续再补充,先写这么多
9、\
#---------------- \ ------------------------------
#反斜杠后面跟元字符去除特殊功能
#反斜杠后面跟普通字符实现特殊功能
# \d 匹配任何十进制数;相当于 [0-9]
print(re.findall('\d', '12sfde 445 rv ')) # ['1', '2', '4', '4', '5']
# \D 匹配任何非数字字符;相当于 [^0-9]
print(re.findall('\D', '12sfde 445 rv ')) #['s', 'f', 'd', 'e', ' ', ' ', 'r', 'v', ' ']
# \s 匹配任何空白字符;相当于 [\t\n\r\f\v]
print(re.findall('\s445', '12sfde 445 rv445 ')) # [' 445']
# \S 匹配任何非空白字符;相当于 [^\t\n\r\f\v]
print(re.findall('\S445', '12sfde 445 rv445 ')) # ['v445']
# \w 匹配任何字母数字字符;相当于 [a-zA-Z0-9]
print(re.findall('\w4', '12sfde 445 rv445 w4 ')) # ['44', 'v4', 'w4']
# \W 匹配任何非字母数字字符;相当于 [^a-zA-Z0-9]
print(re.findall('\W4', '12sfde 445 rv445 w4 4')) # [' 4', ' 4']
# \b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
print(re.findall(r'I\b', 'I am a IjjI')) #['I', 'I']#3个I值匹配到两个I ,所以这里单词在前空格在后
# \B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'
print(re.findall('A\B', 'I am a IjAjIA')) #['A'] IjAjIA中的第一个A
print(re.findall('A\B', 'AI am a IjAjIA')) #['A', 'A'] AI的A 和IjAjIA的第一个A
#-------------------re.search(pattern, string, flags=0)匹配出满足条件的第一个结果 ;re.findall(pattern, string, flags=0)匹配出所有结果
ret = re.search('asd','asxdasd')
print(ret) #<_sre.SRE_Match object; span=(4, 7), match='asd'>
print(ret.group()) # asd
ret = re.search('asd\.','asdxdasd.')
print(ret) #<_sre.SRE_Match object; span=(4, 7), match='asd'>
print(ret.group()) # asd.
ret = re.findall(r'c\\d','asdc\deasd\df')
print(ret)
10、[]
#---------------- [] 字符集------------------------------
# [abcd]
ret = re.findall('a[bcsddxs]', 'abcdfsacddfaddasa,')
print(ret)
# #输出:['ab', 'ac', 'ad', 'as']
# #结论:字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
# [a-z]
ret = re.findall('[a-z]', 'aSxDAcvF')
print(ret)
# #输出:['a', 'x', 'c', 'v']
# #结论:字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
# [^a-z] 取反
ret = re.findall('[^a-z]', 'aSxDAcvF')
print(ret)
# 输出:['S', 'D', 'A', 'F']
# 结论:负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
ret = re.findall('[.ac*,]', 'ab.cd*,')
print(ret)
# 输出:['a', '.', 'c', '*']
# 结论:取消元字符的特殊功能
补充:正则表达式方法
1、 findall():所有结果都返回到一个列表里
2、 search() :返回匹配到的第一个对象(object),对象可以调用group()返回结果
3、 match(): 只在字符串开始匹配,也返回匹配到的第一个对象,对象可以用group
4、 split() 分割字符串 返回到一个列表中
5、 sub() : 用于替换字符串中的匹配项。
re.sub(pattern, repl, string, count=0, flags=0)
pattern : 正则中的模式字符串。
repl : 替换的字符串,也可为一个函数。
string : 要被查找替换的原始字符串。
count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配。
flags : 编译时用的匹配模式,数字形式。
前三个为必选参数,后两个为可选参数
6、 compile() 预编译
当我们在Python中使用正则表达式时,re模块内部会干两件事情:
编译正则表达式,如果正则表达式的字符串本身不合法,会报错;
用编译后的正则表达式去匹配字符串。
那么如果一个正则表达式要重复使用几千次,出于效率的考虑,我们是不是应该先把这个正则先预编译好,接下来重复使用时就不再需要编译这个步骤了,直接匹配,提高我们的效率
# ----------------------match()---------------------------------
ret = re.match('zbc','azbcnmd')
print(ret) #输出: None
if ret: # 内容非None
print(ret.group())
ret = re.match('zbc','zbcnmd')
print(ret) # 输出: <_sre.SRE_Match object; span=(0, 3), match='zbc'>
if ret:
print(ret.group()) # 输出:zbc
# --------------------------split()----------------------------------
ret = re.split('h','zbchxvhnm')
print(ret) #输出:['zbc', 'xv', 'nm']
ret = re.split('[h,m]','zbchxvhnmb')
print(ret) #输出: ['zbc', 'xv', 'n', 'b']
ret = re.split('[h,n]','zbchxvhnmb') # 若旁边无字符 则认为是空''
print(ret) #输出: ['zbc', 'xv', '', 'mb']
#------------------------sub()------------------------------------
import re
phone = "2004-959-559 # 这是一个电话号码"
num = re.sub(r'#.*$', "", phone) # '#.*$':#到字符串末尾;$:匹配字符串的末尾
print ("电话号码 : ", num) # 移除非数字的内容
num = re.sub(r'\D', "", phone) #\D代表任何非数字字符
print ("电话号码 : ", num)
# 输出:
# 电话号码 : 2004-959-559
# 电话号码 : 2004959559
#------------------------compile()------------------------------------
ret1 = re.findall('(\d{3})-(\d{3}-\d{4})', 'My phone number is 012-239-4597')
print(ret1)
ret2 = re.findall('(\d{3})-(\d{3}-\d{4})', 'My phone number is 0125-239-4597 zhang 234')
print(ret2)
re_compile = re.compile(r'(\d{3})-(\d{3}-\d{4})') #编译
ret1 = re_compile.findall('My phone number is 012-239-4597') #使用 不需要重新定义规则,直接使用前面定义的规则 类似于c语言的#define 宏定义
print(ret1)
ret2 = re_compile.findall('My phone number is 025-239-4597 zhang 234') #使用
print(ret2)
#输出:
# [('012', '239-4597')]
# [('125', '239-4597')]
# [('012', '239-4597')]
# [('025', '239-4597')]