简体   繁体   English

用python中的字典值替换正则表达式匹配组

[英]replace a regex match group with a dictionary value in python

I'm working on a hobby project to write a clone of a popular Amiga BBS software program. 我正在做一个爱好项目,写一个流行的Amiga BBS软件程序的克隆。 One of the functions in this program was using a short code feature, much like BBCodes on forums, to change text color and do some screen formatting. 该程序的一个功能是使用短代码功能,就像论坛上的BBCodes一样,可以更改文本颜色并进行一些屏幕格式化。 I'm having trouble trying to figure out how to replace a RegEx matched group that is read in from a text file. 我在试图找出如何替换从文本文件中读入的RegEx匹配组时遇到了麻烦。 with a value from a dictionary. 使用字典中的值。 For example, we have a text file with our short codes in it: 例如,我们有一个文本文件,其中包含我们的短代码:

{c2}************************************************************
**                                                        **
**  {R3}{c7}This is the SYS.INFO file. This file will show the{c2}    **
**  {c7}caller, information that you want to share, about{c2}     **
**  {c7}your BBS.{c2}                                             **
**                                                        **
************************************************************

The dictionary looks like this: 字典看起来像这样:

ansi_colors = {"c0" : "\033[0.30m" , "c1" : "\033[31m" , "c2" : "\033[0.32m" , "c3" : "\033[0.33m" , "c4" : "\033[0.34m" , "c5" : "\033[0.35m" , "c6" : "\033[0.36m" , "c7" : "\033[0.37m" , "c8" : "\033[1m\033[30m" , "ca" : "\033[1m\033[31m" , "cb" : "\033[1m\033[32m" , "cc" : "\033[1m\033[33m" , "cd" : "\033[1m\033[34m" , "ce" : "\033[1m\033[35m" , "cf" : "\033[1m\033[36m" , "cg" : "\033[1m\033[37m" , "R1" : "\033[41m" , "R2" : "\033[42m" , "R3" : "\033[43m" , "R4" : "\033[44m" , "R5" : "\033[45m" , "R6" : "\033[46m" , "R7" : "\033[47m"}

So when the program comes across {c8} for example, it prints the text following it in the appropriate color as specified by the value in the corresponding key of the dictionary. 因此,当程序遇到{c8}时,它会以相应的颜色打印其后面的文本,该颜色由字典的相应键中的值指定。 SO when you come across {R3}{c7}, the app should replace the {R3} with the correct ANSI for reversed text, then the {c7} changes the color of the text to the appropriate color. 因此当您遇到{R3} {c7}时,应用应使用正确的ANSI替换{R3}以反转文本,然后{c7}将文本的颜色更改为适当的颜色。 So White text on a cyan background in this case. 在这种情况下,青色背景上的白色文字。

The trouble I am having, is getting the regex match group, that corresponds with a key, to be replaced with the correct value from the dictionary. 我遇到的麻烦是,获取与密钥对应的正则表达式匹配组,用字典中的正确值替换。 Here is the code I have: 这是我的代码:

#!/usr/bin/env python

import sys
import re

ansiColors = {"c0" : "\033[0.30m" , "c1" : "\033[31m" , "c2" : "\033[0.32m" , "c3" : "\033[0.33m" , "c4" : "\033[0.34m" , "c5" : "\033[0.35m" , "c6" : "\033[0.36m" , "c7" : "\033[0.37m" , "c8" : "\033[1m\033[30m" , "ca" : "\033[1m\033[31m" , "cb" : "\033[1m\033[32m" , "cc" : "\033[1m\033[33m" , "cd" : "\033[1m\033[34m" , "ce" : "\033[1m\033[35m" , "cf" : "\033[1m\033[36m" , "cg" : "\033[1m\033[37m" , "R1" : "\033[41m" , "R2" : "\033[42m" , "R3" : "\033[43m" , "R4" : "\033[44m" , "R5" : "\033[45m" , "R6" : "\033[46m" , "R7" : "\033[47m"}

display = open('sys.infox','r')
for lines in display:
    lines = re.sub(r'(\{)(\w+)(\})', ansiColors[lines.group(2)] , lines)
    print lines.strip('\n')

this code always gives me the error: 这段代码总是给我错误:

Traceback (most recent call last): File "/private/var/folders/k9/z1vjbjwn6c31xts7l07b2m080000gn/T/Cleanup At Startup/newtestmci-431326805.359.py", line 10, in lines = re.sub(r'({)(\\w+)(})', ansiColors[lines.group(2)] , lines) AttributeError: 'str' object has no attribute 'group' 回溯(最近一次调用最后一次):文件“/ private / var / folders / k9 / z1vjbjwn6c31xts7l07b2m080000gn / T / Cleanup At Startup / newtestmci-431326805.359.py”,第10行,行= re.sub(r'({)( \\ w +)(})',ansiColors [lines.group(2)],lines)AttributeError:'str'对象没有属性'group'

I'm lost and just can't wrap my head around it. 我迷路了,无法绕过它。 Anyone have any suggestions?Show me where I am wrong. 有人有什么建议吗?告诉我我错在哪里。 Still new to python, so go easy on me. 对python来说还是新手,所以对我来说很容易。

lines is just a string; lines只是一个字符串; you're trying to use it as a match object. 你正试图将它用作匹配对象。

You can just use a replacement callback to achieve this: 您可以使用替换回调来实现此目的:

def repl(m):
    return ansiColors[m.group(2)]

display = open('sys.infox','r')
for lines in display:
    lines = re.sub(r'(\{)(\w+)(\})', repl , lines)
    print lines.strip('\n')

You are using lines variable as match object when it's still a string 当它仍然是一个字符串时,你使用lines变量作为匹配对象
You can try this: 你可以试试这个:

>>> with open('sys.infox','r') as display : #pythonic way to handle files
...     for lines in display:
...         matches = re.findall(r'(\{)(\w+)(\})', lines)
...         for match in matches:  #if there's match, it will be a list of saved groups, p.e: [('{', 'c2', '}')]
...             lines = re.sub(r'(\{)(\w+)(\})', ansiColors[match[1]] , lines)
...             print lines.strip('\n')
... 
[0.32m************************************************************
**  This is the SYS.INFO file. This file will show the    **
**  This is the SYS.INFO file. This file will show the    **
**  This is the SYS.INFO file. This file will show the    **
**  [0.37mcaller, information that you want to share, about[0.37m     **
**  [0.37mcaller, information that you want to share, about[0.37m     **
**  [0.37myour BBS.[0.37m                                             **
**  [0.37myour BBS.[0.37m  
#!/usr/local/bin/python2.7

import sys
import re

ansiColors = {"c0" : "\033[0.30m" , "c1" : "\033[31m" , "c2" : "\033[0.32m" , "c3" : "\033[0.33m" , "c4" : "\033[0.34m" , "c5" : "\033[0.35m" , "c6" : "\033[0.36m" , "c7" : "\033[0.37m" , "c8" : "\033[1m\033[30m" , "ca" : "\033[1m\033[31m" , "cb" : "\033[1m\033[32m" , "cc" : "\033[1m\033[33m" , "cd" : "\033[1m\033[34m" , "ce" : "\033[1m\033[35m" , "cf" : "\033[1m\033[36m" , "cg" : "\033[1m\033[37m" , "R1" : "\033[41m" , "R2" : "\033[42m" , "R3" : "\033[43m" , "R4" : "\033[44m" , "R5" : "\033[45m" , "R6" : "\033[46m" , "R7" : "\033[47m"}

def replace(matchobj):
  if matchobj.group(2) in ansiColors.keys():
    return ansiColors[matchobj.group(2)]

display = open('input.txt','r')
for lines in display:
    lines = re.sub(r'(\{)(\w+)(\})', replace , lines)
    print lines.strip('\n')

Use repl as a function to get more control.lines.groups(2) will lead to nothing as lines is string. 使用repl作为一个函数来获得更多的control.lines.groups(2)将导致什么,因为行是字符串。

Output:[0.32m************************************************************
**                                                        **
**  [43m[0.37mThis is the SYS.INFO file. This file will show the[0.32m    **
**  [0.37mcaller, information that you want to share, about[0.32m     **
**  [0.37myour BBS.[0.32m                                             **
**                                                        **
************************************************************

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM