Python3 中的 re 模块

re 模块中包含的方法

Match

def match(pattern, string, flags=0):
从字符串开始处进行正则匹配, 成功则返回一个 match object, 不匹配则返回 None
代码示例:

m = re.match('abc[a-z]', "abcabc")
# 一般判断是否匹配直接使用 if 进行判断就行, match object 一直都是 Ture
if m:
    # 匹配成功
print(m)

注意: 如果第一个字符都不匹配就直接返回 None

Match object

接上面的内容, 我们再来看下 m 这个 match object, 控制台输出了 <_sre.SRE_Match object; span=(0, 4), match='abca'>
_sre模块是 C 语言扩展的并实现了 re 模块的大部分功能
span= 是一个二维的 tuple, 展示了匹配的 start 和 end 位置
match= 值是匹配的字符串
match object 更多相关的函数展示文档都可以查询到戳这里, 目前 re 模块中 searchmatchfullmatch方法都会返回 match object

Fullmatch

def fullmatch(pattern, string, flags=0):
这是在 python3.4 中新加的函数, 会匹配整个字符串, 成功则返回一个 match object, 不匹配则返回 None
代码示例:

m = re.match('abc[a-z]', "abcabc")
print(m) # m = None
m_full = re.fullmatch('abc[a-z]', "abca")
print(m_full) # m_full = <_sre.SRE_Match object; span=(0, 4), match='abca'>

整个字符串必须完全匹配对应的正则, 不然就会返回None

def search(pattern, string, flags=0):
search() 会整个查找字符串进行匹配, 成功则返回一个 match object, 不匹配则返回 None
代码示例:

m_s = re.search('a', "1aaaaaaaa")
print(m_s) # <_sre.SRE_Match object; span=(1, 2), match='a'>

Sub

sub(pattern, repl, string, count=0, flags=0):
可以用 repl 根据正则替换 string 中满足条件的字符串, 以最小的单元(leftmost non-overlapping)进行替换, count 代表替换的次数, 返回一个字符串(没有匹配的则返回原始字符串)
代码示例:

m_sub = re.sub('aa', 'b', 'aaaaaaa1a', count=6)
print(m_sub) # bbba1a
m_sub1 = re.sub('cc', 'b', 'aaaaaaa1a', count=6)
print(m_sub1) # None

repl 也可以是一个函数
代码示例:

def re_sub(match_object):
    if match_object.group(0) == 'aa':
        return '你好'
    else:
        return '你不好'

m_sub = re.sub('aa', re_sub, 'aaaaaaa1a', count=6)
print(m_sub) # 你好你好你好a1a

Subn

def subn(pattern, repl, string, count=0, flags=0):
功能和 sub 函数一样, 但是会返回一个 tuple (new_string, number_of_subs_made).
在 3.5 版本如果没有匹配到则会返回一个空的字符串
代码示例:

def re_sub(match_object):
    if match_object.group(0) == 'aa':
        return '你好'
    else:
        return '你不好'
m_subn = re.subn('aa', re_sub, 'aaaaaaa1a', count=6)
print(m_subn) # ('你好你好你好a1a', 3)

Split

def split(pattern, string, maxsplit=0, flags=0):
根据对应的pattern来分割字符串, maxsplit为最大分割次数, 会以 list 的形式返回所分割的字符串数组
代码示例:

ar = re.split(r'\W+', 'Words, words, word') # \W 表示不匹配字母与数字
print(ar) # ['Words', 'words', 'word']
ar1 = re.split('a', 'bbbabbbabbb')
print(ar1) # ['bbb', 'bbb', 'bbb']
# 设置只分割一次
ar2 = re.split('a', 'bbbabbbabbb', maxsplit=1)
print(ar2) # ['bbb', 'bbbabbb']
# 但是如果以组的形式进行分割, 并且最开始和最后的字符都满足正则, 则前后都会出现一个空字符串
ar3 = re.split(r'(\W+)', '...words, words...') # \W 表示不匹配字母与数字
print(ar3) # ['', '...', 'words', ', ', 'words', '...', ''] 前后都有 ''
ar4 = re.split(r'(\W+)', 'words, words...') # \W 表示不匹配字母与数字
print(ar4) # ['words', ', ', 'words', '...', ''] 后面满足则后面出现 ''

当然也会有一些特例, 比如:

ar5 = re.split('x*', 'axbc')
print(ar5) # ['a', 'bc'] 
# python3.6/re.py:212: FutureWarning: split() requires a non-empty pattern match.

上面的代码执行后会抛出一个FutureWarning类型的警告意思是: split() 函数需要一个非空的匹配, 因为这里 x* 会匹配 0 次或多次 x, 所以 0 次也可以, 按道理讲 a x b c, 都应该匹配, 但是这里却只匹配的 x, 未来版本会对此类匹配进行修改, 所以还是不要使用 empty pattern, 未来 python 版本返回结果可能更改为['', 'a', 'b', 'c', '']
并且在 3.5 版本中增加了对空字符串匹配的异常, 抛出一个 ValueError

ar6 = re.split("^$", "aaaa")
print(ar6) # ValueError: split() requires a non-empty pattern match.

Findall

def findall(pattern, string, flags=0):
会找出所有匹配的字符串并以数组的形式返回, 没有找到则会返回一个空的数组
代码示例:

f = re.findall('a', 'bbbabbbabbb')
print(f) # ['a', 'a']
f1 = re.findall('a', 'b')
print(f1) # [] 没找到
f2 = re.findall('a*', 'aaaaaaaaa')
print(f2) # ['aaaaaaaaa', '']
# pattern 包含多个子组, 则会以 list of tuple 的形式返回
f3 = re.findall('(a)|(aa)', 'aaaaa')
print(f3) # [('a', ''), ('a', ''), ('a', ''), ('a', ''), ('a', '')]
f4 = re.findall('(aa)|(a)', 'aaaaa')
print(f4) # [('aa', ''), ('aa', ''), ('', 'a')]

Finditer

def finditer(pattern, string, flags=0):
功能同 findall() 只不过是返回一个迭代器

Compile

def compile(pattern, flags=0):
对正则进行编译, 我们来看下会返回什么

c = re.compile('a|b', re.IGNORECASE) # IGNORECASE 忽略大小写
print(c) # re.compile('a|b', re.IGNORECASE)
print(type(c)) # <class '_sre.SRE_Pattern'>

会生成一个 SRE_Pattern 对象, 并且里面可以继续调用上面已经介绍过的函数, 会保存 flagspattern
接上面

# def findall(self, string, pos=0, endpos=-1):
# SRE_Pattern 对象的函数普遍都会多一个 endpos=-1 和 startPos=0, 默认整个字符串
f = c.findall('abdsda')
print(f) # ['a', 'b', 'a']

Purge

def purge():
清楚正则表达式缓存

Escape

def escape(pattern)
除了 ASCII 码字母和数字已经 ‘_’, 所有字符都将变为转义(escape)状态
注: 3.3 版本后 ‘_’ 不再转义

print(re.escape('你好呢?abc.123!@#')) # \你\好\呢\?abc\.123\!\@\#

这个函数不可以用于sub()subn()替换, 除非反斜杠应该被转义

digits_re = r'\d+'
print(digits_re == '\\d+') # Ture
print(digits_re, digits_re.replace('\\', r'\\')) # \d+ \\d+
sample = '/usr/sbin/sendmail - 0 errors, 12 warnings'
print(re.sub(digits_re, digits_re.replace('\\', r'\\'), sample)) # /usr/sbin/sendmail - \d+ errors, \d+ warnings

模式

  • I IGNORECASE 无视大小写 re.I
  • L LOCALE 本地化字符集, 各国的语言字符集可能不一样, 但是中国是一样的, 基本不怎么需要用 re.L
  • M MULTILINE 主要针对 ^$, 把文本进行多行处理
m_l = """hello
nihao
haobuhao
"""
r = re.findall('^\w+', m_l)
print(r) # ['hello']
r = re.findall('^\w+', m_l, re.M)
print(r) # ['hello', 'nihao', 'haobuhao']
r = re.findall('\w+$', m_l)
print(r) # ['hello']
r = re.findall('\w+$', m_l, re.M)
print(r) # ['hello', 'nihao', 'haobuhao']
  • S  DOTALL .可以匹配任何字符, 包括换行符
  • X VERBOSE 冗余模式, 忽略空白和注释
# 以下代码在 pycharm 中颜色都会有变化, 确实厉害
re.compile('''
id # id
|
name # name
''', re.X)
re.compile('''
id # id
|
name # name
''')
  • U (可忽略) UNICODE 把\w \W \s \S等这些元字符按照 Unicode 的标准来考虑re.U 官方文档中似乎去除了 re.U 相关内容戳这里(python3 中除去了 re.U 反之使用了 re.A)
  • A ASCII 使 \w, \W, \b, \B, \d, \D, \s, \S 仅仅进行 ASCII 匹配替代了原来的 unicode 匹配
# \s 为空格, \u3000是中文下的unicode空格符, \x20 是空格的 ASCII 数值
pattern = re.compile(r"a\s+b", re.A)
m = pattern.findall(u"dsadadsada\x20b") # 匹配成功
m = pattern.findall("dsadadsada\u3000b") # 匹配失败
m = pattern.findall("a b") # 匹配成功
pattern = re.compile(r"a\s+b")
m = pattern.findall("dsadadsada\u3000b") # 匹配成功
m = pattern.findall("a b") # 匹配成功

猜你喜欢

转载自blog.csdn.net/u010435828/article/details/80198909