【问题标题】:Regex and a sequences of patterns?正则表达式和一系列模式?
【发布时间】:2009-06-27 19:45:29
【问题描述】:

有没有办法多次匹配一个模式 (e\d\d),将每个模式捕获到一个组中?例如,给定字符串..

blah.s01e24e25

..我希望得到四个组:

1 -> blah
2 -> 01
3 -> 24
4 -> 25

要使用的明显正则表达式是(在 Python 正则表达式中:

import re
re.match("(\w+).s(\d+)e(\d+)e(\d+)", "blah.s01e24e25").groups()

..但我也想匹配以下任一:

blah.s01e24
blah.s01e24e25e26

你似乎不能这样做 (e\d\d)+,或者说你可以,但它只捕获最后一次出现:

>>> re.match("(\w+).s(\d+)(e\d\d){2}", "blah.s01e24e25e26").groups()
('blah', '01', 'e25')
>>> re.match("(\w+).s(\d+)(e\d\d){3}", "blah.s01e24e25e26").groups()
('blah', '01', 'e26')

我想在单个正则表达式中执行此操作,因为我有多个模式来匹配电视剧集文件名,并且不想复制每个表达式来处理多个剧集:

\w+\.s(\d+)\.e(\d+) # matches blah.s01e01
\w+\.s(\d+)\.e(\d+)\.e(\d+) # matches blah.s01e01e02
\w+\.s(\d+)\.e(\d+)\.e(\d+)\.e(\d+) # matches blah.s01e01e02e03

\w - \d+x\d+ # matches blah - 01x01
\w - \d+x\d+\d+ # matches blah - 01x01x02
\w - \d+x\d+\d+\d+ # matches blah - 01x01x02x03

.. 等等许多其他模式。

另一件使事情复杂化的事情——我希望将这些正则表达式存储在一个配置文件中,因此不需要使用多个正则表达式和函数调用的解决方案——但如果这被证明是不可能的,我将只允许用户添加简单的正则表达式

基本上,有没有办法使用正则表达式捕获重复模式?

【问题讨论】:

    标签: python regex sequences


    【解决方案1】:

    分两步进行,一是找出所有数字,二是拆分它们:

    import re
    
    def get_pieces(s):
        # Error checking omitted!
        whole_match = re.search(r'\w+\.(s\d+(?:e\d+)+)', s)
        return re.findall(r'\d+', whole_match.group(1))
    
    print get_pieces(r"blah.s01e01")
    print get_pieces(r"blah.s01e01e02")
    print get_pieces(r"blah.s01e01e02e03")
    
    # prints:
    # ['01', '01']
    # ['01', '01', '02']
    # ['01', '01', '02', '03']
    

    【讨论】:

      【解决方案2】:

      捕获的组数等于括号组数。查看findallfinditer 来解决您的问题。

      【讨论】:

        【解决方案3】:

        非分组括号: (?:asdfasdg)

        不必出现: (?:adsfasdf)?

        c = re.compile(r"""(\w+).s(\d+)
                               (?:
                                    e(\d+)
                                    (?:
                                          e(\d+)
                                    )?
                                )?
                       """, re.X)
        

        c = re.compile(r"""(\w+).s(\d+)(?:e(\d+)(?:e(\d+))?)?""", re.X)
        

        【讨论】:

          【解决方案4】:

          思考问题后,我想我有一个更简单的解决方案,使用命名组。

          用户(或我)可以使用的最简单的正则表达式是:

          (\w+\).s(\d+)\.e(\d+)
          

          文件名解析类将第一组作为节目名称,第二组作为季号,第三组作为剧集号。这涵盖了大部分文件。

          我将允许这些不同的命名组:

          (?P<showname>\w+\).s(?P<seasonnumber>\d+)\.e(?P<episodenumber>\d+)
          

          为了支持多集,我将支持两个命名组,例如 startingepisodenumberendingepisodenumber 以支持 showname.s01e01-03 之类的东西:

          (?P<showname>\w+\)\.s(?P<seasonnumber>\d+)\.e(?P<startingepisodenumber>\d+)-(?P<endingepisodenumber>e\d+)
          

          最后,允许名称匹配 episodenumber\d+episodenumber1episodenumber2 等)的命名组:

          (?P<showname>\w+\)\.
          s(?P<seasonnumber>\d+)\.
          e(?P<episodenumber1>\d+)
          e(?P<episodenumber2>\d+)
          e(?P<episodenumber3>\d+)
          

          它仍然可能需要为不同数量的e01s 复制模式,但永远不会有两个非连续剧集的文件(如show.s01e01e03e04),因此使用starting/endingepisodenumber 组应该可以解决这个问题,对于用户遇到的奇怪情况,他们可以使用episodenumber\d+ 组名

          这并不能真正回答模式序列问题,但它解决了导致我提出这个问题的问题! (我仍然会接受另一个答案,该答案显示如何在一个正则表达式中匹配 s01e23e24...e27 - 如果有人解决了这个问题!)

          【讨论】:

            【解决方案5】:

            也许是这样的?

            def episode_matcher(filename):
                m1= re.match(r"(?i)(.*?)\.s(\d+)((?:e\d+)+)", filename)
                if m1:
                    m2= re.findall(r"\d+", m1.group(3))
                    return m1.group(1), m1.group(2), m2
                # auto return None here
            
            >>> episode_matcher("blah.s01e02")
            ('blah', '01', ['02'])
            >>> episode_matcher("blah.S01e02E03")
            ('blah', '01', ['02', '03'])
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-12-15
              • 1970-01-01
              • 1970-01-01
              • 2017-03-25
              相关资源
              最近更新 更多