代码之家  ›  专栏  ›  技术社区  ›  dbr

正则表达式和一系列模式?

  •  4
  • dbr  · 技术社区  · 15 年前

    有匹配图案的方法吗( e\d\d )好几次,把每个人都分成一组?例如,给定字符串..

    blah.s01e24e25
    

    …我希望有四组:

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

    显然要使用的regex是(在python regex中:

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

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

    \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
    

    …等等,对于许多其他模式。

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

    基本上,是否有一种方法可以使用regex捕获重复模式?

    5 回复  |  直到 15 年前
        1
  •  5
  •   RichieHindle    15 年前

    分两步进行,一步查找所有数字,然后一步将其拆分:

    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
  •  1
  •   Rorick    15 年前

    捕获的组数等于括号组数。看 findall finditer 为了解决你的问题。

        3
  •  1
  •   Adrian Panasiuk    15 年前

    非分组括号: ?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
  •  0
  •   dbr    15 年前

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

    用户(或我)可以使用的最简单的regex是:

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

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

    我将允许以下几个不同的命名组:

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

    为了支持多集,我将支持两个命名组,类似 startingepisodenumber endingepisodenumber 支持像 showname.s01e01-03 :

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

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

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

    它仍然需要复制不同数量的模式。 e01 但是不会有一个文件有两个非连续的剧集(比如 show.s01e01e03e04 ),所以使用 starting/endingepisodenumber 小组应该解决这个问题,对于奇怪的情况,用户可以使用 上位号\d+ 组名

    这并不能真正回答模式顺序问题,但它解决了导致我问它的问题!(我还是会接受另一个显示如何匹配的答案 s01e23e24...e27 在一个regex中-如果有人解决了这个问题!)

        5
  •  0
  •   tzot    15 年前

    也许是那样?

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