【问题标题】:Python: hexadecimal regular expression questionPython:十六进制正则表达式问题
【发布时间】:2010-08-03 10:31:37
【问题描述】:

我想解析一个名为 Docklight 的串行监控程序的输出(我强烈推荐它) 它输出“十六进制”字符串:或一系列(两个大写十六进制数字后跟一个空格)。对应的正则表达式为:([0-9A-F]{2} )+ 例如:'05 03 DA 4B 3F '

当程序检测到特定的字符序列时,它会将 cmets 放在“十六进制”字符串中。例如:

'05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'

cmets 是以下格式的字符串 ' .+ '(一系列字符,前面有一个空格,后面有一个空格)

我想摆脱 cmets。例如,上面过滤的“十六进制”字符串将是:

'05 03 04 01 0A 03 08 0B BD AF 0D 0A '

我该如何使用正则表达式来做到这一点?

【问题讨论】:

  • @SRT:假设 cmets 中没有 2 个字母的十六进制单词,否则输入会不明确。但是,cmets 可以包含带有(连续)十六进制数字的较长单词
  • ok.看看 greg 的回答
  • 请注意:我通常用来测试正则表达式的是这个免费的在线测试器,它也适用于 Python 表达式(python 和 .net 表达式的大部分是相同的风格):regexhero.net/tester
  • 你如何推荐一个没有易于解析输出选项的包?
  • @JM:我推荐它,因为它是我发现的唯一可以在 Windows PC 上成功处理杀手级串行通信的工具。如果 cmets(用户定义的)遵循某种语法(例如,包含方括号),那么解析将是小菜一碟。我的客户不是这样

标签: python regex regex-negation


【解决方案1】:

你可以试试re.findall():

>>> a='05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'
>>> re.findall(r"\b[0-9A-F]{2}\b", a)
['05', '03', '04', '01', '0A', '03', '08', '0B', 'BD', 'AF', '0D', '0A']

正则表达式中的\b 匹配“单词边界”。

当然,如果串行监视器插入THIS BE THE HEADER 之类的内容,您的输入就会不明确。

【讨论】:

    【解决方案2】:

    使用你的正则表达式

    hexa = '([0-9A-F]{2} )+'
    " ".join(re.findall(hexa, line))
    

    【讨论】:

      【解决方案3】:

      假设插入的字符串不包含匹配项,查找所有十六进制数字可能会更容易:

      >>> data = '05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'
      >>> import re
      >>> pattern = re.compile("[0-9A-F]{2} ")
      >>> "".join(pattern.findall(data))
      '05 03 04 01 0A 03 08 0B BD AF AD 0D 0A '
      

      否则,您可以使用插入的字符串前面有两个空格的事实:

      >>> data = '05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'
      >>> re.sub("(  .*?)(?=( [0-9A-F]{2} |$))","",data)
      '05 03 04 01 0A 03 08 0B BD AF 0D 0A'
      

      这使用前瞻来计算插入的字符串何时结束。它查找由空格包围的十六进制字符串或源字符串的结尾。

      【讨论】:

        【解决方案4】:

        实际使用正则表达式否定的解决方案怎么样? ;)

        result = re.sub(r"[ ]+(?:(?!\b[0-9A-F]{2}\b).)+", "", subject)
        

        【讨论】:

        • 也不错!测验:哪个更丑,你的正则表达式否定还是我的否定后视?大声笑
        • 它太接近了,但如果你给你的词添加边界(我认为你应该这样做),你将成为明显的赢家。或者我应该说 unclear 获胜者? ;)
        • 你的愿望就是我的命令,我将它们添加到前瞻版本中;)
        【解决方案5】:

        虽然您已经收到了两个找到所有十六进制数字的答案,但直接正则表达式的情况与此相同,它可以找到所有看起来不像十六进制数字的文本(假设是大写/小写的两个字母/数字 0- 9 和 A-F 范围,后跟一个空格)。

        类似这样的东西(对不起,我不是pythoneer,但你明白了):

        newstring = re.sub(r"[^ ]+(?<![0-9A-Fa-f ]{2}|^.)", "", yourstring)
        

        它的工作原理是“回头看”。它找到每个连续的非空格子字符串,然后用(?&lt;!....) 负向回顾。它说:“如果前两个字符不是十六进制数字,则成功”。末尾的小^. 防止错误匹配字符串的第一个字符。

        编辑

        正如 Alan Moore 所建议的,这里有一个带有积极前瞻表达式的相同想法:

        newstring = re.sub(r"(?>\b[0-9A-Fa-f ]{2}\b)", "", yourstring)
        

        【讨论】:

        • 对这类事情使用前瞻通常更容易(而且可能更有效)。
        • @Alan,确实可能是这样,但您会更快地得到误报。在这种情况下,使用单词边界,它可以工作。我更新了答案。
        【解决方案6】:

        为什么是正则表达式?对我来说更多的 Pythonic 是(固定为 hexdigit 而非常规数字):

        command='05 03 04 01 0A  The Header 03 08 0B BD AF  The PAYLOAD 0D 0A  The Footer'
        print ' '.join(com for com in command.split()
                       if len(com)==2 and all(c.upper() in '0123456789ABCDEF' for c in com))
        

        【讨论】:

          猜你喜欢
          • 2019-04-25
          • 1970-01-01
          • 1970-01-01
          • 2014-03-05
          • 2011-10-03
          • 2021-06-04
          • 2017-02-27
          • 2012-07-12
          相关资源
          最近更新 更多