【问题标题】:replace a regex match group with a dictionary value in python用python中的字典值替换正则表达式匹配组
【发布时间】:2014-09-02 05:09:40
【问题描述】:

我正在从事一个爱好项目,以编写流行的 Amiga BBS 软件程序的克隆。该程序中的一个功能是使用短代码功能,就像论坛上的 BBCodes 一样,可以更改文本颜色并进行一些屏幕格式化。我无法弄清楚如何替换从文本文件中读取的 RegEx 匹配组。带有字典中的值。例如,我们有一个包含短代码的文本文件:

{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}                                             **
**                                                        **
************************************************************

字典如下所示:

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"}

因此,例如,当程序遇到 {c8} 时,它会以字典相应键中的值指定的适当颜色打印其后的文本。因此,当您遇到 {R3}{c7} 时,应用程序应将 {R3} 替换为正确的 ANSI 反转文本,然后 {c7} 将文本的颜色更改为适当的颜色。所以在这种情况下,青色背景上的白色文本。

我遇到的麻烦是,将与键对应的正则表达式匹配组替换为字典中的正确值。这是我的代码:

#!/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')

这段代码总是给我错误:

Traceback(最近一次调用最后一次): 文件“/private/var/folders/k9/z1vjbjwn6c31xts7l07b2m080000gn/T/Cleanup At Startup/newtestmci-431326805.359.py”,第 10 行,在 行 = re.sub(r'({)(\w+)(})', ansiColors[lines.group(2)] , 行) AttributeError: 'str' 对象没有属性 'group'

我迷路了,我无法绕开它。有人有什么建议吗?告诉我我错在哪里。对python还是很陌生,所以对我来说放轻松。

【问题讨论】:

    标签: python regex replace


    【解决方案1】:

    lines 只是一个字符串;您正在尝试将其用作匹配对象。

    您可以使用替换回调来实现此目的:

    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')
    

    【讨论】:

      【解决方案2】:

      当它仍然是一个字符串时,你正在使用 lines 变量作为匹配对象
      你可以试试这个:

      >>> 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  
      

      【讨论】:

      • 感谢您提供 Pythonic 打开文件的方式并给出了很好的解释。 +1
      【解决方案3】:
      #!/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')
      

      使用 repl 作为函数来获取更多控制。lines.groups(2) 将导致任何结果,因为 lines 是字符串。

      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                                             **
      **                                                        **
      ************************************************************
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-08-10
        • 1970-01-01
        • 1970-01-01
        • 2015-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-13
        相关资源
        最近更新 更多