Python之正则表达式

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']

从整个文本搜索,找到就返回一个内存地址,通过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是一个合法的标识符

取值方法:

  1. 根据组的别名取值
  2. 根据索引取值
  3. 根据类似字典的键值对取值,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'])  # 类似字典的键值对方式取值

  转载请注明: 浩大大 Python之正则表达式

  目录