re.sub 使用技巧:捕获分组

re.sub 使用技巧:捕获分组


1. re.sub

调用格式:

re.sub(pattern, repl, string, count=0, flags=0)

这里记录一下当repl参数为函数时的使用方法。

方法一:

import re

def dashrepl(matchobj):
	if matchobj.group(0) == '-': return ' '
	else: return '-'
	
re.sub('-{1,2}', dashrepl, 'pro----gram-files')

方法二:

import re

dashrepl = lambda x:" " if x.group(0)=="-" else "-"	
re.sub('-{1,2}', dashrepl, 'pro----gram-files')

------------------------------ 2020-09-30 更新 ------------------------------

2 关于re.sub 不能如re.findall/match/search 一样捕获分组进行替换或者删除

上样例代码:

import re

s = 'Data: year=2018, monthday=1, month=5, some other text'
reg = r"year=(\d{4}), monthday=(\d{1}), month=(\d{1})"

re.findall:

re.findall(reg,s)

output: [('2018', '1', '5')]

re.sub:

re.sub(reg, "", s)

output: 'Data: , some other text'

由结果可看到:re.sub 替换的是匹配到的所有,在样例中则是包含"year=…"

Stackoverflow 上有说明原因:python re.findall vs re.sub

解决办法:

StackOverflow上有一些解决办法,但是大都不通用或者需要更改你的正则表达式和替换表达式,或者复杂,没有一个通用的方法,故自己一番琢磨后,把解决办法分享出来,如下:

使用上文[1 re.sub](#1 re.sub)的repl方法

def repl(match):
    _reg = "|".join(match.groups())
    return re.sub(_reg, "",match.group(0)) if _reg else ""

调用:

re.sub(reg,repl, s)

output: 'Data: year=, monthday=, month=, some other text'

注意此方法仅适用于删除, 进阶使用替换的时候,传入替换字符:

r = "我是替换字符"
def repl(match):
    _reg = "|".join(match.groups())
    return re.sub(_reg, r,match.group(0)) if _reg else r

# 调用
re.sub(reg,repl, s)

output: 'Data: year=我是替换字符, monthday=我是替换字符, month=我是替换字符, some other text'

此方法适用于多分组情况或者无分组情况, 当然如果所有需求里都不会出现 没有分组 的情况时, 可以将末尾的 if _reg else r去掉,以节省性能,如下:

r = "我是替换字符"
def repl(match):
    _reg = "|".join(match.groups())
    return re.sub(_reg, r,match.group(0))

# 调用
re.sub(reg,repl, s)

------------------------------ 更新 ------------------------------

如果匹配结果是多行值:上述不奏效,提供一种思路:

如果有一个分组,且分组匹配出来是多行的字符串,这时使用re.sub+str.replace结合:

def repl2(match):
    _reg = match.groups()[0]
    return match.group(0).replace(_reg, "")
  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值