You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python2.7中re.sub报'unmatched group'错误,求列表转字典方案修正

正则表达式在Python2.7中抛出"unmatched group"错误的原因及修复

问题背景

有如下字符串列表,每个元素是空格分隔的键值对:

listA = [
'abcd1-2 4d4e',
'xyz0-1 551',
'foo 3ea',
'bar1 2bd',
'mc-mqisd0-2 77a'
]

需求是将其转换为字典,其中带数字范围的键(如xyz0-1)需要展开为多个键(如abcd1、abcd2)并对应相同值,预期结果如下:

{
'abcd1': '4d4e',
'abcd2': '4d4e',
'xyz0': '551',
'xyz1': '551',
'foo': '3ea',
'bar1': '2bd',
'mc-mqisd0': '77a',
'mc-mqisd1': '77a',
'mc-mqisd2': '77a',
}

编写的Python3兼容函数如下,但在Python2.7环境(Ansible插件)中执行时抛出unmatched group错误:

def listFln(listA):
    import re
    fL = []
    for i in listA:
      aL = i.split()[0]
      bL = i.split()[1]
      comp = re.sub('^(.+?)(\d+-\d+)?$',r'\1',aL)
      cmpCountR = re.sub('^(.+?)(\d+-\d+)?$',r'\2',aL)
      if cmpCountR.strip():
        nStart = int(cmpCountR.split('-')[0])
        nEnd = int(cmpCountR.split('-')[1])
        for j in range(nStart,nEnd+1):
          fL.append(comp + str(j) + ' ' + bL)
      else:
        fL.append(i)

    return(dict([k.split() for k in fL]))

错误信息:

cmpCountR = re.sub('^(.+?)(\d+-\d+)?$',r'\2',aL)
  File "/usr/lib64/python2.7/re.py", line 151, in sub
    return _compile(pattern, flags).sub(repl, string, count)
  File "/usr/lib64/python2.7/re.py", line 275, in filter
    return sre_parse.expand_template(template, match)
  File "/usr/lib64/python2.7/sre_parse.py", line 800, in expand_template
    raise error, "unmatched group"

错误原因

问题出在正则表达式的可选捕获组处理差异上:

  • 正则^(.+?)(\d+-\d+)?$中的第二个组(\d+-\d+)?是可选的(末尾的?表示匹配0次或1次)。
  • 当处理不带数字范围的键(如foo、bar1)时,第二个组完全没有匹配到。
  • Python3中,re.sub会将未匹配的捕获组引用(如\2)替换为空字符串;但Python2.7的re模块不允许引用未匹配的捕获组,直接抛出"unmatched group"错误。

修复方案

改用re.match获取匹配对象,通过group()方法安全获取捕获组内容,未匹配的组返回None,再手动替换为空字符串即可。修正后的兼容Python2.7的函数如下:

def listFln(listA):
    import re
    # 提前编译正则,提升循环内执行效率
    pattern = re.compile(r'^(.+?)(\d+-\d+)?$')
    fL = []
    for i in listA:
        # 直接拆分键值对,简化赋值
        aL, bL = i.split()
        match = pattern.match(aL)
        comp = match.group(1)
        # 未匹配到第二个组时,用空字符串替代None
        cmpCountR = match.group(2) or ''
        if cmpCountR.strip():
            # 一次性转换起始/结束数字
            nStart, nEnd = map(int, cmpCountR.split('-'))
            for j in range(nStart, nEnd + 1):
                fL.append(comp + str(j) + ' ' + bL)
        else:
            fL.append(i)
    # 生成最终字典
    return dict(k.split() for k in fL)

内容的提问来源于stack exchange,提问作者Vijesh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:15:43