【问题标题】:Find length of string matched by regex查找正则表达式匹配的字符串长度
【发布时间】:2015-04-02 23:14:00
【问题描述】:

我正在尝试编写一个脚本来解析由编译器/链接器生成的映射文件,如下所示:

%SEGMENT_SECTION
                                                      Start Address  End Address
--------------------------------------------------------------------------------
Segment Name: S1_1, Segment Type: .bss                0A000000       0A050F23
--------------------------------------------------------------------------------
area1_start.o (.bss)                                  0A000000       0A000003
...

                                                      Start Address  End Address
--------------------------------------------------------------------------------
Segment Name: S2_1, Segment Type: .bss                0A050F24       0A060000
--------------------------------------------------------------------------------
area2_start.o (.bss)                                  0A000000       0A000003

...

%NEXT_SECTION

我目前正在编写几个正则表达式(python 的 re 模块)来解析它,但我想以一种非常易于阅读的方式编写它们,这样解析起来非常简单。本质上:

with open('blah.map') as f:
    text = f.read()

# ... Parse the file to update text to be after the %SEGMENT_SECTION

match = segment_header_re.match(text)
seg_name, seg_type, start_addr, end_addr = match.groups()
# ... (Do more with matched values)

text = text[len(match.matched_str):]

# Parse the remainder of text

但是,我不知道如何获取匹配字符串的长度,就像我的match.matched_str 伪代码一样。我在 python 的 re 文档中没有看到任何内容。有没有更好的方法来进行这种类型的解析?

【问题讨论】:

    标签: python regex parsing


    【解决方案1】:

    对于您想要实现的目标,请使用match.span 方法。

    >>> 
    >>> s = 'The quick brown fox jumps over the lazy dog'
    >>> m = re.search('brown', s)
    >>> m.span()
    (10, 15)
    >>> start, end = m.span()
    >>> s[end:]
    ' fox jumps over the lazy dog'
    >>> 
    

    或者只是 match.end 方法。

    >>> s[m.end():]
    ' fox jumps over the lazy dog'
    >>> 
    

    另一种选择是使用regular expression objects,它可以采用posendpos 参数来将搜索限制为字符串的一部分。

    >>> s = 'The quick brown fox jumps over the lazy dog'
    >>> over = re.compile('over')
    >>> brown = re.compile('brown')
    >>> m_brown = brown.search(s)
    >>> m_brown.span()
    (10, 15)
    >>> m_over = over.search(s)
    >>> m_over.span()
    (26, 30)
    

    brown 的匹配结束时开始搜索over

    >>> match = over.search(s, pos = m_brown.end())
    >>> match.group()
    'over'
    >>> match.span()
    (26, 30)
    

    over 的匹配末尾开始搜索brown,不会产生匹配。

    >>> match = brown.search(s, m_over.end())
    >>> match.group()
    
    Traceback (most recent call last):
      File "<pyshell#71>", line 1, in <module>
        match.group()
    AttributeError: 'NoneType' object has no attribute 'group'
    >>> print(match)
    None
    >>> 
    

    对于长字符串和多次搜索,使用带有起始位置参数的正则表达式对象肯定会加快速度。

    【讨论】:

    • OP 想要匹配字符串的长度,而不是它在完整字符串中的位置。在这种情况下,他会想要s[5:],因为'brown' 的长度是5。你应该这样做s[end - start:]
    • @iCodez .. 我可能是错的,但无论问题中的文本如何,看起来代码都试图通过删除已找到的内容来缩短正在搜索的 text。这就是我在这个答案中要解决的问题。
    • 似乎我误解了正则表达式页面中组的定义,并认为我无法获得整个字符串。谢谢!
    【解决方案2】:

    您可以使用.group() 方法。整个匹配的字符串可以通过match.group(0)检索:

    text = text[len(match.group(0)):]
    

    演示:

    >>> import re
    >>> re.match('(a)bc(d)', 'abcde').group(0)  # 'e' is excluded since it wasn't matched
    'abcd'
    >>>
    >>> # You can also get individual capture groups by number (starting at 1)
    >>> re.match('(a)bc(d)', 'abcde').group(1)
    'a'
    >>> re.match('(a)bc(d)', 'abcde').group(2)
    'd'
    >>>
    

    但是请注意,如果没有匹配,这将引发 AttributeError

    >>> re.match('xyz', 'abcde').group(0)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'NoneType' object has no attribute 'group'
    >>>
    

    您可能希望在调用匹配对象上的方法之前实施检查以确保匹配成功。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-03-03
      • 2018-07-16
      • 2015-06-15
      • 2017-08-29
      • 2019-01-04
      • 1970-01-01
      • 2014-11-26
      • 2018-11-24
      相关资源
      最近更新 更多