首页 > 解决方案 > python 正则表达式:一个或两个带分隔符

问题描述

我需要一个正则表达式来匹配a,ba;b.

我不能写a|b|a;b,因为ab包含命名组,如果我尝试这样做,我会得到一个例外: 将组名“a”重新定义为组 8;在第 60 位是第 3 组

a;?b也不起作用,因为ab不能匹配。

你会如何解决这个问题?re图书馆有可能吗?我听说还有一个图书馆叫pyparsing. 那会更适合这个问题吗?


背景:这是这个问题的后续问题。因为似乎无法通过 urwid 或 curses 中的颜色代码,所以我试图解码从 git 获得的颜色代码,以便 urwid 可以重新编码这些颜色。

为避免复制和粘贴出现问题,我在以下正则表达式中省略了前导控制字符:

工作正则表达式,除了它与测试程序[1m中使用的(粗体)不匹配:

reo_color_code = re.compile(
    r'\['
    r'((?P<series>[01]);)?'
    r'((?P<fgbg>[34])(?P<color>[0-7]))?'
    r'm'
)

不编译正则表达式:

reo_color_code = re.compile(
    r'\['
    r'('
        r'((?P<series>[01]))'
        r'|'
        r'((?P<fgbg>[34])(?P<color>[0-7]))'
        r'|'
        r'((?P<series>[01]));((?P<fgbg>[34])(?P<color>[0-7]))'
    r')'
    r'm'
)

抛出异常

re.error: redefinition of group name 'series' as group 8; was group 3 at position 60

标签: pythonregexpyparsing

解决方案


既然您在这里询问了 pyparsing,那么 pyparsing 解析器会是什么样子:

import pyparsing as pp

integer = pp.pyparsing_common.integer
ansi_expr = ("[" 
             + integer("d1") 
             + pp.Optional(';' + integer("d2")) 
             + pp.oneOf(list(pp.alphas.lower()))("trailing"))

ansi_expr.runTests("""\
    [1m
    [23;34z
    """)

带测试输出:

[1m
['[', 1, 'm']
- d1: 1
- trailing: 'm'

[23;34z
['[', 23, ';', 34, 'z']
- d1: 23
- d2: 34
- trailing: 'z'

推荐阅读