我需要一个正则表达式来匹配a
,b
或a;b
。
我无法写a|b|a;b
,因为a
和b
包含命名组,如果我尝试这样做,则会出现异常:
将组名“ a”重新定义为组8;是第3组的第60名。
a;?b
也不起作用,因为ab
必须不匹配。
您将如何解决?
re
库是否有可能?
我听说还有一个名为pyparsing
的图书馆。会更适合这个问题吗?
背景:这是this one的后续问题。 因为似乎无法通过urwid或curses中的颜色代码,所以我试图对从git中获得的颜色代码进行解码,以便urwid可以重新编码这些颜色。
为避免复制和粘贴出现问题,我在以下正则表达式中省略了前导控制字符:
有效的正则表达式,但与a test program中使用的[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
答案 0 :(得分:1)
在这种情况下,我不会尝试构建单个正则表达式来解决整个问题,相反,我将实现如下所示的方法(也使用re
但在不同的级别) :
def get_info(s):
if s.startswith('[') and s.endswith('m'):
p = s[1:-1]
if ';' in p:
m = re.match('^([01]);([34])([0-7])$', p)
else:
m = re.match('^([01])$|^([34])([0-7])$', p)
if m:
return tuple(m.groups())
return None, None, None
您可以像这样使用它:
>>> serie, fgbg, color = get_info('[1;37m')
>>> serie, fgbg, color
('1', '3', '7')
PS:没有做太多测试。希望对您有所帮助。
答案 1 :(得分:1)
这是用于破解ANSI终端序列的更通用的正则表达式:
\[(\d+)(?:;(\d+))?([a-z])
如果您想按名称访问组,请使用以下命令:
\[(?P<d1>\d+)(?:;(?P<d2>\d+))?(?P<trailing>[a-z])
我没有给整数值提供任何有意义的名称,因为它们会随尾随的字母字符而变化(也可以大于1位数字)。
对于以后的正则表达式开发工作,https://regex101.com是一个很棒的交互式页面,可以帮助您解决所有问题。
答案 2 :(得分:1)
自从您询问有关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'