Python之正则表达式
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。
Python 自1.5版本起增加了 re 模块,它提供 Perl 风格的正则表达式模式。
re 模块使 Python 语言拥有全部的正则表达式功能。
1. 单个字符匹配
符号 | 作用 |
---|---|
“\w” | 匹配字母(包含中文)或数字或下划线 |
“\W” | 匹配除字母(包含中文)或数字或下划线以外的其他字符 |
“\s” | 匹配空格、制表符、换行符 |
“\S” | 匹配所有空格、制表符、换行符以外的其他字符 |
“\d” | 匹配所有阿拉伯数字0-9 |
“\D” | 匹配所有阿拉伯数字0-9以外的其他字符 |
“\A” | 获取满足规则的开头 |
“^” | 获取满足规则的开头 |
“\Z” | 获取满足规则的结尾 |
“$“ | 获取满足规则的结尾 |
“\n” | 匹配换行符\n |
“” | 匹配制表符\t |
1.1 字母(包含中文)或数字或下划线相关
# \w 匹配字母(包含中文)或数字或下划线
s1 = '(森七abv123_#$'
print(re.findall('\w\w', s1))
# ['森七', 'ab', 'v1', '23']
print(re.findall('\w', s1))
# ['森', '七', 'a', 'b', 'v', '1', '2', '3', '_']
# \W 匹配除字母(包含中文)或数字或下划线以外的其他字符
print(re.findall('\W\w', s1))
# ['(森']
1.2 空格、制表符、换行符相关
# \s 匹配空格、制表符、换行符
print(re.findall('\s', ' 森七abcd*(_\t),\n'))
# [' ', '\t', '\n']
# \S 匹配所有空格、制表符、换行符以外的其他字符
print(re.findall('\S', ' 森七abcd*(_\t),\n'))
# ['森', '七', 'a', 'b', 'c', 'd', '*', '(', '_', ')', ',']
# 匹配 \n
print(re.findall('\n', 'ab\ncde\n'))
# ['\n', '\n']
# 匹配 \t
print(re.findall('\t', 'ab\tcde\t\t'))
# ['\t', '\t', '\t']
1.3 阿拉伯数字0-9相关
# \d 匹配所有阿拉伯数字0-9
print(re.findall('\d\d\d', '1234567890I 森七123*'))
# ['123', '456', '789', '123']
# \D 匹配所有阿拉伯数字0-9以外的其他字符
print(re.findall('\d\D', '1234567890I 森七123*'))
# ['0I', '3*']
1.4 获取满足规则的开头
# \A 和 ^ 获取满足规则的开头
print(re.findall('\Aab', 'abc 森七2353453DDK'))
# ['ab']
print(re.findall('\Aabc', 'abc 森七2353453DDK'))
# ['abc']
print(re.findall('^abc', 'abc 森七2353453DDK'))
# ['abc']
1.5 获取满足规则的结尾
# \Z 和 $ 获取满足规则的结尾
print(re.findall('DDK\Z', 'abc 森七2353453DDK'))
# ['DDK']
print(re.findall('3DDK$', 'abc 森七2353453DDK'))
# ['3DDK']
# 完全匹配
print(re.findall('^abc$', 'abc'))
# ['abc']
2. (元字符)重复字符匹配
符号 | 作用 |
---|---|
“.” | 默认匹配除\n之外的任意一个字符,若指定 flag=re.DOTALL ,则匹配任意字符,包括\n |
“?” | 匹配0次或1次由?左边字符组成的片段 |
“*” | 匹配0次或多次由*左边字符组成的片段 |
“+” | 匹配1次或多次由+左边字符组成的片段 |
“{m}” | 匹配{}左边的字符m次 |
“{m,n}” | 匹配{}左边的字符m到n次 |
“.*” | 贪婪匹配,匹配带有.*左边字符的任意字符 |
“.*?” | 限制贪婪匹配的非贪婪匹配,匹配带有.*左边字符的字符 |
“[0-9]” | 匹配任何数字(一个中括号代表一个字符 ) |
“[a-z]” | 匹配任何小写字母(一个中括号代表一个字符 ) |
“[A-Z]” | 匹配任何大写字母(一个中括号代表一个字符 ) |
“[a-zA-Z0-9]” | 匹配任何字母及数字(一个中括号代表一个字符 ) |
“[^0-9]” | 匹配除了数字外的字符,^ 在 [] 内表示取反 |
“(…)” | 分组匹配 |
“|” | 匹配符号两边的任意一个,相当于或 |
2.1 匹配任意字符
# . 匹配任意字符,除去 \n
print(re.findall('a.b', 'ab aab a*b a2b a\tb a牛b a\nb'))
# ['aab', 'a*b', 'a2b', 'a\tb', 'a牛b']
# 不除去 \n
print(re.findall('a.b', 'ab aab a*b a2b a\tb a牛b a\nb', re.DOTALL))
# ['aab', 'a*b', 'a2b', 'a\tb', 'a牛b', 'a\nb']
2.2 匹配0次或1次由 ? 左边字符组成的片段
# 可匹配出:ab,b
print(re.findall('a?b', 'ab abb aab asb'))
# ['ab', 'ab', 'b', 'ab', 'b']
print(re.findall('a?b', 'ababbaab'))
# ['ab', 'ab', 'b', 'ab']
print(re.findall('a?b', 'ab aab abb aabb acb agb'))
# ['ab', 'ab', 'ab', 'b', 'ab', 'b', 'b', 'b']
2.3 匹配0次或多次由 * 左边字符组成的片段
# 可匹配出:b,ab,aaa...aab
print(re.findall('a*b', 'ababbaaaababb'))
# ['ab', 'ab', 'b', 'aaaab', 'ab', 'b']
2.4 匹配1次或多次由 + 左边字符组成的片段
# 可匹配出:ab,a....b
print(re.findall('a+b', 'ababbaaaababb'))
# ['ab', 'ab', 'aaaab', 'ab']
2.5 匹配 {} 左边的字符m次
# 可匹配出:连续的三次a带上一个b
print(re.findall('a{3}b', 'abaaaabbaaaababb'))
# ['aaab', 'aaab']
2.6 匹配 {} 左边的字符m到n次
# 可匹配出:ab,aab,aaab,aaaab
print(re.findall('a{1,4}b', 'abaaaabbaaaababb'))
# ['ab', 'aaaab', 'aaaab', 'ab']
2.7 贪婪匹配
# 可匹配出:ab,a任意字符个数b
print(re.findall('a.*b', 'ababbabb aaabsb dddb'))
# ['ababbabb aaabsb dddb']
2.8 非贪婪匹配
# 可匹配出:ab,a...b
print(re.findall('a.*?b', 'ababbabb aaabsbdddb'))
# ['ab', 'ab', 'ab', 'aaab']
2.9 字符组 []
print(re.findall('a[abcd]b', 'aababbaddbaccb'))
# ['aab', 'abb']
print(re.findall('a[abcd][abcd]b', 'aababbaddbaccb'))
# ['abab', 'addb', 'accb']
print(re.findall('a[0-9]b', 'a1ba2basba55b'))
# ['a1b', 'a2b']
print(re.findall('a[a-z]b', 'aabaccbagb'))
# ['aab', 'agb']
print(re.findall('a[A-Z]b', 'aDFbaRbAsbaHB'))
# ['aRb']
print(re.findall('a[a-zA-Z]b', 'aAb aWb aeb a*b arb a_b'))
# ['aAb', 'aWb', 'aeb', 'arb']
print(re.findall('a[-*+]b', 'a-b a*ba/bab+6b'))
# ['a-b', 'a*b']
2.10 取反
# 在括号中 ^ 代表取反
print(re.findall('a[^0-9]b', 'a1b a2b asb a55b'))
# ['asb']
2.11 分组
print(re.findall('(.*?)_sb', '?!@aaa_sb bbb_sb ccc__sb'))
# ['?!@aaa', ' bbb', ' ccc_']
# 分组:返回整个的匹配片段
print(re.findall('compan(?:y|ies)', 'To many companies have gone bankrupt, and the next one is other company'))
# ['companies', 'company']
2.12 匹配两边任意一个
# | 匹配左边或者右边
print(re.findall('森七|ab|cd', '森七abcdlog'))
['森七', 'ab', 'cd']
3. RE模块常用方法
3.1 findall
找出所有的满足条件的字符串并返回一个列表
print(re.findall('^abc$', 'abc'))
# ['abc']
3.2 search
从整个文本搜索,找到就返回一个内存地址,通过group()方法取值
ret = re.search('\d[5-9]', '森七2356')
print(ret) # 返回一个内存地址
# <_sre.SRE_Match object; span=(3, 5), match='35'>
print(ret.group()) # 获取匹配的值
# 35
3.3 match
从头匹配字符并返回一个内存地址,直到字符不在规则内停止返回
ret = re.match('[1-9][0-9]+', '2098654654b234')
# <_sre.SRE_Match object; span=(0, 10), match='2098654654'>
print(ret.group())
# 2098654654
3.4 split
按照任意多个分隔符进行分割,可以指定 maxsplit=x
表示分割x次,默认为0,不限制次数
print(re.split('[|;,:]', 'aaa|bbb;ccc:ddd'))
# ['aaa', 'bbb', 'ccc', 'ddd']
print(re.split('[|;,:]', 'aaa|bbb;ccc:ddd', 1))
# ['aaa', 'bbb;ccc:ddd']
3.5 sub
按照要求进行替换,可以指定 count=x
表示替换几次,默认为0,不限制次数
print(re.sub('aaa', 'bbb', 'aaa和bbb,bbb和aaa'))
# bbb和bbb,bbb和bbb
print(re.sub('aaa', 'bbb', 'aaa和bbb,bbb和aaa', 1))
# bbb和bbb,bbb和aaa
3.6 compile
用于编译正则表达式,自定义匹配规则
obj = re.compile('\d{2}')
print(obj.findall('asfaf244124fa234sd23'))
# ['24', '41', '24', '23', '23']
3.7 finditer
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回,比 findall 更加节省内存。
可以通过 for 循环遍历获取到内存地址后,用 group() 方法取值,或 next() 方法取值
s1 = '123|567,森七,678'
obj = re.finditer('\d{3}', s2)
print(obj) # 迭代器内存地址
print(next(obj).group()) # next()方法取一次值
for item in obj: # for循环获取内存地址
print(item.group()) # 取值
4. 命名分组
命名分组就是给具有默认分组编号的组另外再给一个别名。命名分组的语法格式如下:
(?P<name>正则表达式) #name是一个合法的标识符
取值方法:
- 根据组的别名取值
- 根据索引取值
- 根据类似字典的键值对取值,python 3.6及以上有效
t1 = '''
小明 男 20
小红 女 21
小绿 男 22
'''
ret = re.finditer('(?P<name>\w{2}) (?P<sex>\w) (?P<age>\d{2})', t1)
for i in ret:
print(i.group('name', 'sex', 'age')) # 根据组的别名取值
for i in ret:
print(i.group(1, 2, 3)) # 根据索引取值
for i in ret:
print(i['name'], i['sex'], i['age']) # 类似字典的键值对方式取值