【问题标题】:Match last occurrence with regex用正则表达式匹配最后一次出现
【发布时间】:2013-08-24 19:38:35
【问题描述】:

我想使用正则表达式匹配最后一次出现的模式。

我有一些这样的文本结构:

Pellentesque habitant morbi tristique senectus et netus et
lesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae
ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam
egestas <br>semper<br>tizi ouzou<br>Tizi Ouzou<br>                        

我想匹配两个&lt;br&gt; 之间的最后一个文本,在我的情况下为&lt;br&gt;Tizi Ouzou&lt;br&gt;,最好是Tizi Ouzou 字符串

注意最后一个&lt;br&gt;后面有一些空格

我试过了:

<br>.*<br>\s*$

但它会选择从第一个 &lt;br&gt; 到最后一个的所有内容。

注意:我在 python 上,我正在使用 pythex 来测试我的正则表达式

【问题讨论】:

  • 试试.*? 而不是.*
  • @WaleedKhan 这无济于事

标签: python regex


【解决方案1】:

对我来说最清晰的方法是:

>>> re.findall('<br>(.*?)<br>', text)[-1]
'Tizi Ouzou'

【讨论】:

    【解决方案2】:

    使用内置 str 函数的非正则表达式方法:

    text = """
    Pellentesque habitant morbi tristique senectus et netus et
    lesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae
    ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam
    egestas <br>semper<br>tizi ouzou<br>Tizi Ouzou<br>       """
    
    res = text.rsplit('<br>', 2)[-2]
    #Tizi Ouzou
    

    【讨论】:

      【解决方案3】:

      查看相关问题:you shouldn't parse HTML with regex。请改用正则表达式解析器。对于 Python,我听说 Beautiful Soup 是要走的路。

      无论如何,如果你想使用正则表达式,你需要确保.* 不能超过另一个&lt;br&gt;。为此,在使用每个字符之前,我们可以使用 lookahead 来确保它不会启动另一个 &lt;br&gt;

      <br>(?:(?!<br>).)*<br>\s*$
      

      【讨论】:

        【解决方案4】:

        您可以在具有简化字符类的贪婪量词中使用(假设您之间没有标签&lt;br&gt;):

        <br>([^<]*)<br>\s*$
        

        <br>((?:[^<]+|<(?!br>))*)<br>\s*$
        

        允许标签在里面。

        由于您搜索的字符串是Tizi Ouzou,没有&lt;br&gt;,您可以提取第一个捕获组。

        【讨论】:

        • @m.buettner:你是对的,因为字符串是从左到右分析的,并在&lt;br&gt;第一次出现时停止
        【解决方案5】:

        [^&lt;&gt;]* 而不是.* 怎么样:

        import re
        
        
        text = """Pellentesque habitant morbi tristique senectus et netus et
        lesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae
        ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam
        egestas <br>semper<br>tizi ouzou<br>Tizi Ouzou<br> """
        
        
        print re.search('<br>([^<>]*)<br>\s*$', text).group(1)
        

        打印

        Tizi Ouzou
        

        【讨论】:

          【解决方案6】:

          试试:

          re.match(r'(?s).*<br>(?=.*<br>)(.*)<br>', s).group(1)
          

          它首先消耗所有数据直到最后一个&lt;br&gt;,然后回溯直到它通过前瞻检查在它之后还有另一个&lt;br&gt;,然后提取它们之间的内容。

          它产生:

          Tizi Ouzou
          

          编辑:无需前瞻。基于 m.buettner

          评论的替代方案(结果相同)
          re.match(r'(?s).*<br>(.*)<br>', s).group(1)
          

          【讨论】:

          • 不需要前瞻 - 前瞻后的模式检查完全相同的东西。
          • @m.buettner:谢谢。将该版本添加到答案中。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-18
          • 2016-03-18
          • 1970-01-01
          相关资源
          最近更新 更多