Python使用re模块进行文本处理

正则表达式概念
正则表达式是由一系列字符和特殊符号构成的字串,它提供文本的高级匹配模式,包括搜索,替换等功能。
匹配原则
1)正确性:能够正确地匹配出目标字符串
2)排他性:除了目标字符串之外尽可能少的匹配其他内容
3)全面性:尽可能地考虑到目标字符串的所有情况,无遗漏

一、元字符

元字符匹配规则举例
普通字符匹配相对应的字符In    : re.findall('ab',"abndefabrp")
Out : ['ab', 'ab']
^匹配目标字符串的开头位置In    : re.findall('^Jerry',"Jerry, hello!")
Out : ['Jerry']
$匹配目标字符串的结束位置In    : re.findall('Jerry$',"Hi, Jerry")
Out : ['Jerry']
或关系符|匹配|两侧任意的正则表达式即可In    : re.findall('com|cn',"www.baidu.com/www.jseea.cn")
Out : ['com', 'cn']
.匹配除换行符外的任意一个字符In    : re.findall('杨.郎',"杨五郎,杨六郎,杨七郎")
Out : ['杨五郎', '杨六郎', '杨七郎']
()将位于()内的内容作为一个整体,又称正则表达式的内部分组参见 三、正则表达式分组
[]匹配位于[字符集]中的任意一个字符In    : re.findall('[aeiou]',"What wolf will do?")
Out : ['a', 'o', 'i', 'o']
[^]匹配除字符集以外的任意一个字符In    : re.findall('[^a-z]', "python之re模块")
Out : ['之', '模', '块']
*匹配前一个字符出现0次或多次In    : re.findall('wo*', "wooooo~~what beautiful!")
Out : ['wooooo', 'w']
+匹配前一个字符出现1次或多次In    : re.findall('[A-Z][a-z]+',"Hello Python")
Out : ['Hello', 'Python']
?匹配前一个字符出现0次或1次In    : re.findall('-?[0-9]+', "整数:28, -188")
Out : ['28', '-188']
{n}匹配前一个字符出现n次In    : re.findall('1[0-9]{10}',"Tele:13770962365")
Out : ['13770962365']
{m,n}匹配前一个字符出现m到n次(n≥m)In    : re.findall('[1-9][0-9]{5,8}',"number:1259296994")
Out : ['1320916376']
\w
\W
\w匹配普通字符,\W匹配非普通字符
普通字符:指数字、字母、下划线、汉字
In    : re.findall('\w+',"web_port = 8888")
Out : ['web_port', '8888']
\d
\D
\d匹配数字字符,\D匹配非数字字符In    : re.findall('\d{1,5}',"Mysql: 3306, http:80")Out : ['3306', '80']
\s
\S
\s匹配空字符,\S匹配非空字符
空字符:指\r \n \t \v \f 字符
In    : re.findall('\w+\s+\w+',"hello python")
Out : ['hello python']
\b
\B
\b表示单词边界,\B表示非单词边界
单词边界:指数字、字母(汉字)、下划线与其他字符的交界位置
In    : re.findall(r'\bhave\b',"Let's have a test.")
Out : ['have']
\A
\Z
\A匹配目标字符串的开头位置,\Z匹配目标字符串的结尾位置
1.当不涉及多行匹配时,\A和^,\Z和$没有区别
2.\A和\Z无论设置多行匹配与否,效果都是一样
In    : re.findall(r'\ALine', 'Line one\nword on line two\n')
Out : ['Line']
In    : re.findall(r'^word', 'Line one\nword on line two\n')
Out : []
In    : re.findall(r'\Aword', 'Line one\nword on line two\n')
Out : []
In    : re.findall(r'^word', 'Line one\nword on line two\n', flags=re.M)
Out : ['word']
In    : re.findall(r'\Aword', 'Line one\nword on line two\n', flags=re.M)
Out : []
================分割线================
In    : re.findall(r'two\Z', 'Line one\nword on line two')
Out : ['two']
In    : re.findall(r'two\Z', 'Line one\nword on line two\n')
Out : []
In    : re.findall(r'one\Z', 'Line one\nword on line two')
Out : []
\ 1.\与特定字符结合起到转义的作用
2.因为某些特殊字符作为正则匹配的元字符,若使用正则表达式匹配特殊字符本身,则需要在特殊字符前加\起到转义的效果。
3.正则表达式中的特殊符号有 * + ? ^ $ [] () {} | \
In    : re.findall('-?\d+\.?\d*',"314,-314,3.14,-3.14")
Out : ['314', '-314', '3.14', '-3.14']

二、贪婪模式和非贪婪模式

1、概念
1)贪婪模式默认情况下,匹配重复的元字符(* + ? {m,n})总是尽可能多地向后匹配内容。
2)非贪婪模式:又称懒惰模式,让匹配重复的元字符尽可能少地向后匹配内容。
2、贪婪模式转换为非贪婪模式在匹配重复的元字符后加 ? 即可

* 转为非贪婪模式 *?
+ 转为非贪婪模式 +?
? 转为非贪婪模式 ??
{m,n}转为非贪婪模式 {m,n}?

In : re.findall('ab*?','abbbbbbbbbbbbbbbb')
Out: ['a']
In : re.findall('ab+?','abbbbbbbbbbbbbbbb')
Out: ['ab']
In : re.findall('ab??','abbbbbbbbbbbbbbbb')
Out: ['a']
In : re.findall('ab{2,8}','abbbbbbbbbbbbbbbb')
Out: ['abbbbbbbb']
In : re.findall('ab{2,8}?','abbbbbbbbbbbbbbbb')
Out: ['abb']
# 值得注意的是,采用非贪婪模式时,若正则表达式中,表示非贪婪模式的?号后还跟有其他正则表达式,那么非贪婪模式不生效,举例如下
In : re.findall('ab+?cd*', 'abbbcddddd')
Out: ['abbbcddddd']

三、正则表达式分组

1、概念
在正则表达式中,以小括号()建立正则表达式的内部分组(子组),子组是正则表达式的一部分,可以作为内部整体操作对象。
2、应用场景

  • 作为整体操作,改变元字符的操作对象
In : re.search(r'ab+',"ababababab").group()
Out: 'ab'
In : re.search(r'(ab)+',"ababababab").group()  # 改变+的操作对象
Out: 'ababababab'
In : re.search(r'东|西\w{1,3}','东成西就').group()
Out: '东'
In : re.search(r'(东|西)\w{1,3}', '东成西就').group()  # 改变|号的操作对象
Out: '东成西就'
  • 获取子组对应的内容
In : re.search(r'(https|http|ftp|file)://\S+', "https://www.baidu.com").group()
Out: 'https://www.baidu.com'
In : re.search(r'(https|http|ftp|file)://\S+', "https://www.baidu.com").group(1)
Out: 'https'

3、捕获组
概念:正则表达式中可以给子组命名,用来赋予子组意义,我们称被命名的子组为捕获组。
格式:(?P<name>pattern)
注意事项
1)一个正则表达式中可以包含多个子组
2)子组可以嵌套,但是不建议嵌套复杂结构;子组序列号一般从外到内,从左到右计数

In : re.search(r'(?P<dog>ab)+',"ababababab").group('dog')
Out: 'ab'
In : re.search(r'((ab)c)d(?P<cat>ef)', "abcdef").group()
Out: 'abcdef'
In : re.search(r'((ab)c)d(?P<cat>ef)', "abcdef").group(1)
Out: 'abc'
In : re.search(r'((ab)c)d(?P<cat>ef)', "abcdef").group(2)
Out: 'ab'
In : re.search(r'((ab)c)d(?P<cat>ef)', "abcdef").group(3)
Out: 'ef'
In : re.search(r'((ab)c)d(?P<cat>ef)', "abcdef").group('cat')
Out: 'ef'

四、Python re模块的使用

import re
# re模块属性方法
sample = "abababababababababa"

# ========================================re对象操作========================================
# ------------------------------compile方法 生成正则表达式对象-------------------------------
regex = re.compile(r'b', flags=0)
# Out: re.compile(r'b', re.UNICODE)
"""
函数原型:compile(pattern, flags=0)
参数:pattern 正则表达式
	  flags 功能标志位,扩展正则表达式的匹配
返回值:正则表达式对象
"""

# ----------------------方法findall split sub subn返回匹配到的内容序列-----------------------
findall_list = re.findall(r'ab', sample, flags=0)          # 返回类型为列表
# Out: ['ab', 'ab', 'ab', 'ab', 'ab', 'ab', 'ab', 'ab', 'ab']
"""
函数原型:findall(pattern, string, flags=0)
参数:pattern 正则表达式
	  string 目标字符串
	  flags 功能标志位,扩展正则表达式的匹配
返回值:匹配的内容列表,如果正则表达式有子组则只能获取到子组对应的内容
"""
split_list = re.split(r'b', sample, 3, flags=0)            # 返回类型为列表
# Out: ['a', 'a', 'a', 'ababababababa']
"""
函数原型:split(pattern, string, maxsplit=0, flags=0)
参数:maxsplit 最多进行的分隔次数,默认全部分隔
返回值:分隔后的内容列表
"""
sub_str = re.sub(r'b', ' ', sample, 3, flags=0)            # 返回类型为字符串
# Out: 'a a a ababababababa'
"""
函数原型:sub(pattern, repl, string, count=0, flags=0)
参数:repl 替换的字符串(可以是字符串或函数)
	  count 最多替换几处,默认替换全部
返回值:替换后的字符串
"""
subn_tup = re.subn(r'b', ' ', sample, 3, flags=0)          # 返回类型为包含字符串和整型值的元组
# Out: ('a a a ababababababa', 3)
"""
函数原型:subn(pattern, repl, string, count=0, flags=0)
返回值:替换后的字符串 和 替换了几处
"""
# --------------------方法finditer fullmatch match search返回匹配结果对象--------------------
re_finditer = re.finditer(r'ab', sample, flags=0)          # 返回类型为迭代器对象,任意位置匹配
# Out: <callable_iterator at 0x516dd30>
"""
函数原型:finditer(pattern, string, flags=0)
返回值:返回一个保存匹配对象的迭代器对象
"""
re_fullmatch = re.fullmatch(r'ab', sample, flags=0)        # 返回类型为match匹配对象,匹配整个目标字符串(python2不支持该方法)
# Out: None
"""
函数原型:fullmatch(pattern, string, flags=0)
返回值:如果整个string匹配到正则表达式,就返回一个相应的匹配对象,否则返回None
"""
re_match = re.match(r'ab', sample, flags=0)                # 返回类型为match匹配对象,从开始位置匹配
# Out: <_sre.SRE_Match object; span=(0, 2), match='ab'>
re.match(r'b', sample, flags=0)
# Out: None
"""
函数原型:match(pattern, string, flags=0)
返回值:如果从开始位置匹配到了正则表达式,就返回一个相应的匹配对象,否则返回None
注意:即便是MULTILINE多行模式,该方法只匹配字符串的开始位置,而不匹配每行开始
"""
re_search = re.search(r'ab', sample, flags=re.IGNORECASE)  # 返回类型为match匹配对象,任意位置匹配,匹配目标字符串中第一个符合的内容
# Out: <_sre.SRE_Match object; span=(0, 2), match='ab'>
"""
函数原型:search(pattern, string, flags=0)
返回值:扫描整个目标字符串,找到符合匹配样式的第一个位置,并返回一个相应的匹配对象,否则返回None
"""
# ======================================regex对象操作=======================================
# 称regex对象为正则表达式对象(正则对象)
# -----------------------方法findall split sub subn返回匹配到的内容序列----------------------
regex_list = regex.findall(sample, 0, len(sample))         # 返回类型为列表,收尾索引参数可以省略
# Out: ['b', 'b', 'b', 'b', 'b', 'b', 'b', 'b', 'b']
"""
函数原型:findall(string[, pos[, endpos]])
参数:pos 目标字符串开始匹配的索引位置,默认为0
	  endpos 目标字符串结束匹配的索引位置,默认为目标字符串的长度
返回值:匹配的内容列表
"""
regex_split_list = regex.split(sample, 3)                  # 返回类型为列表
# Out: ['a', 'a', 'a', 'ababababababa']
"""
函数原型:split(string, maxsplit=0)
返回值:分隔后的内容列表
"""
regex_sub_str = regex.sub(' ', sample, 3)                  # 返回类型为字符串
# Out: 'a a a ababababababa'
"""
函数原型:sub(repl, string, count=0)
返回值:替换后的字符串
"""
regex_subn_tup = regex.subn(' ', sample, 3)                # 返回类型为包含字符串和整型值的元组
# Out: ('a a a ababababababa', 3)
"""
函数原型:subn(repl, string, count=0)
返回值:替换后的字符串 和 替换了几处
"""
# ---------------------方法finditer fullmatch match search返回匹配结果对象-------------------
re_finditer2 = regex.finditer(sample, 0, len(sample))      # 返回类型为迭代器对象,任意位置匹配
# Out: <callable_iterator at 0x50f91d0>
"""
函数原型:finditer(string[, pos[, endpos]])
返回值:返回一个保存匹配对象的迭代器对象
"""
re_fullmatch2 = regex.fullmatch(sample, 0, len(sample))    # 返回类型为match匹配对象,匹配整个目标字符串(Python2不支持该方法)
# Out: None
"""
函数原型:fullmatch(string[, pos[, endpos]])
返回值:如果整个string匹配到正则表达式,就返回一个相应的匹配对象,否则返回None
"""
re_match2 = regex.match(sample, 0, len(sample))            # 返回类型为match对象,从开始位置匹配
# Out: None
>>> pattern = re.compile('o')
>>> pattern.match("dog")        # 因为‘o’不是目标字符串的开始位置,所以匹配不到
>>> pattern.match("dog", 1)     # 因为‘o’是目标字符串的第二个字符,所以匹配得到
# Out: <_sre.SRE_Match object; span=(1, 2), match='o'>
"""
函数原型:match(string[, pos[, endpos]])
返回值:如果从开始位置匹配到了正则表达式,就返回一个相应的匹配对象,否则返回None
"""
re_search2 = regex.search(sample, 0, len(sample))          # 返回类型为match对象,任意位置匹配,匹配目标字符串中第一个符合的内容
# Out: <_sre.SRE_Match object; span=(1, 2), match='b'>
"""
函数原型:search(string[, pos[, endpos]])
返回值:扫描整个目标字符串,并寻找第一个匹配的位置,返回一个相应的匹配对象,否则返回None
"""
# -----------------------------属性 flag groupindex groups pattern--------------------------
mark = regex.flags                   # 正则匹配标记
num = regex.groups                   # 获正则表达式中组的数量
d = regex.groupindex                 # 映射由(?P<id>)定义的命名符号组(捕获组)和序号组合的字典;若没有符号组,则字典为空
re.compile('(?P<cat>b)', flags=0).groupindex
# Out: mappingproxy({'cat': 1})
p = regex.pattern                    # 获取编译对象的原始字符串
# Out: 'b'

# =====================================match对象操作========================================
# 匹配对象总是有一个布尔值True,若没有的话无法返回匹配对象,而是返回None,所以可以用if语句来判断是否匹配
# ----------------------------------match对象的属性变量-------------------------------------
pos = re_match.pos                   # 匹配的目标字符串开始位置
enpos = re_match.endpos              # 匹配的目标字符串结束位置
re_obj = re_match.re                 # 正则表达式对象
dest_str = re_match.string           # 目标字符串
lastgroup = re_match.lastgroup       # 获取最后一组的名称,若子组或子组名称不存在,则返回None
lastindex = re_match.lastindex       # 获取最后一组的序号
# ----------------------------------match对象的属性方法-------------------------------------
re_match2.span([group])              # 获取匹配内容的起止位置,返回类型为元组
"""
参数:group 表示子组序号,为可选变量;默认为0,表示整个匹配
返回值:返回表示起止位置的元组,若未产生匹配,则返回(-1, -1)
"""
re_match2.start([group])             # 返回匹配内容的开始位置索引,若未匹配则返回-1
re_match2.end([group])               # 返回匹配内容的结束位置索引,若未匹配则返回-1
re_match2.group([group1, ...])       # 返回类型为对应匹配内容的字符串或元组
>>> m = re.match(r"(\w+) (\w+)", "Isaac Newton, physicist")
>>> m.group(0)          # The entire match <=> m[0]
'Isaac Newton'
>>> m.group(1)          # The first parenthesized subgroup <=> m[1]
'Isaac'
>>> m.group(2)          # The second parenthesized subgroup <=> m[2]
'Newton'
>>> m.group(1, 2)       # Multiple arguments give us a tuple.
('Isaac', 'Newton')
"""
参数:默认参数(不带参数)表示获取整个匹配对象内容,若是序列号或组名则表示返回对应子组的内容
返回值:返回匹配对象的对应匹配内容
"""
re_match2.groups(default=None)       # 返回获取子组对应内容
>>> re.match(r"(\d+)\.(\d+)", "24.1632").goups()
# Out: ('24', '1632')
>>> re.match(r"(\d+)\.?(\d+)?", "24").groups()  # 子组2未匹配到内容,默认值None
# Out: ('24', None)
>>> re.match(r"(\d+)\.?(\d+)?", "24").groups("hello")
# Out: ('24', 'hello')
"""
参数:default 给未匹配到内容的子组赋值,默认为None
返回值:返回一个元组,包含所有匹配的子组内容
""" 
re_match2.groupdict(default=None)    # 返回捕获组字典,组名为键,对应内容为值
>>> m = re.match(r"(?P<first_name>\w+) (?P<last_name>\w+)", "Malcolm Reynolds")
>>> m.groupdict()
# Out: {'first_name': 'Malcolm', 'last_name': 'Reynolds'}

五、re模块调用关系

re模块接口关系

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值