【问题标题】:Python regular expression multi patterns, extracting right groupsPython正则表达式多模式,提取正确的组
【发布时间】:2015-11-21 04:57:14
【问题描述】:

我在 Python 中编写了一个正则表达式,它应该搜索 season/s 和 episode/e 后跟一个数字。正如您在我的代码中看到的那样,我支持各种寻找我想要的模式。

import re

episode = re.compile(r"""(?:s|season)(?:\s)(\d+)(?:e|x|episode|\n)(?:\s)(\d+)| # s 01e 02
                        (?:s|season)(\d+)(?:e|x|episode|\n)(?:\s)(\d+)| # s01e 02
                        (?:s|season)(?:\s)(\d+)(?:e|x|episode|\n)(\d+)| # s 01e02
                        (?:s|season)(\d+)(?:e|x|episode|\n)(\d+)| # s01e02
                        (?:s|season)(\d+)(?:.*)(?:e|x|episode|\n)(\d+)| # s01 random123 e02
                        (?:s|season)(?:\s)(\d+)(?:.*)(?:e|x|episode|\n)(?:\s)(\d+)| # s 01 random123 e 02
                        (?:s|season)(?:\s)(\d+)(?:.*)(?:e|x|episode|\n)(\d+)| # s 01 random123 e02
                        (?:s|season)(\d+)(?:.*)(?:e|x|episode|\n)(?:\s)(\d+) # s01 random123 e 02
                        """, re.VERBOSE)

test="Hello seinfeld season 01episode 22 foo bar"

match = re.search(episode, test)
print match.group(1), match.group(2)

以下代码将按预期输出01 22。 但是如果test 字符串是这样的:

test="Hello seinfeld season 01 episode 22 foo bar"

我怎样才能知道要使用哪个组?这意味着我不知道test 有什么价值。

编辑:也许我可以检查所有组的价值,如果确实如此,请使用该特定组。但这似乎是一种错误的做法。

【问题讨论】:

  • r"""\s*season\s*(\d+)\s*(?:e|x|episode)\s*(\d+)""" 适用于示例测试提供的字符串等等。请为所有需要扩展的案例提供一组测试字符串。

标签: python regex regex-group


【解决方案1】:

如何将每个正则表达式模式分解成一个列表,其中每个元素都包含一个正则表达式模式?如果您需要添加/删除更多模式,这将帮助您组织正则表达式模式,同时划分每个变体。您可能还想使用正则表达式命名组。

我对原始示例进行了额外的两项更改:1) 单个模式,2) 命名组,如下所示:

import re

pattern1 = re.compile(r"""(?:s|season)(?:\s)(?P<s>\d+)(?:e|x|episode|\n)(?:\s)(?P<ep>\d+) # s 01e 02""", re.VERBOSE)
pattern2 = re.compile(r"""(?:s|season)(?P<s>\d+)(?:e|x|episode|\n)(?:\s)(?P<ep>\d+) # s01e 02""", re.VERBOSE)
pattern3 = re.compile(r"""(?:s|season)(?:\s)(?P<s>\d+)(?:e|x|episode|\n)(?P<ep>\d+) # s 01e02""", re.VERBOSE)
pattern4 = re.compile(r"""(?:s|season)(?P<s>\d+)(?:e|x|episode|\n)(?P<ep>\d+) # s01e02""", re.VERBOSE)
pattern5 = re.compile(r"""(?:s|season)(?P<s>\d+)(?:.*)(?:e|x|episode|\n)(?P<ep>\d+) # s01 random123 e02""", re.VERBOSE)
pattern6 = re.compile(r"""(?:s|season)(?:\s)(?P<s>\d+)(?:.*)(?:e|x|episode|\n)(?:\s)(?P<ep>\d+) # s 01 random123 e 02""", re.VERBOSE)
pattern7 = re.compile(r"""(?:s|season)(?:\s)(?P<s>\d+)(?:.*)(?:e|x|episode|\n)(?P<ep>\d+) # s 01 random123 e02""", re.VERBOSE)
pattern8 = re.compile(r"""(?:s|season)(?P<s>\d+)(?:.*)(?:e|x|episode|\n)(?:\s)(?P<ep>\d+) # s01 random123 e 02""", re.VERBOSE)

patterns = [pattern1, pattern2, pattern3, pattern4, pattern5, pattern6, pattern7, pattern8 ]

test="Hello seinfeld season 01episode 22 foo bar"

for idx, p in enumerate(patterns):
    m = re.search(p, test)
    if m:
        print('MATCHED PATTERN: {}'.format( patterns[idx].pattern ) )
        print('    SEASON:  {}'.format( m.group('s')) )
        print('    EPISODE: {}'.format( m.group('ep')) )

输出:

MATCHED PATTERN: (?:s|season)(?:\s)(?P<s>\d+)(?:e|x|episode|\n)(?:\s)(?P<ep>\d+) # s 01e 02
    SEASON:  01
    EPISODE: 22

MATCHED PATTERN: (?:s|season)(?:\s)(?P<s>\d+)(?:.*)(?:e|x|episode|\n)(?:\s)(?P<ep>\d+) # s 01 random123 e 02
    SEASON:  01
    EPISODE: 22

当然,您需要添加一些额外的逻辑来选择要采用的匹配项(例如,您可以轻松地选择采用第一个完整的匹配项),但至少这可以让您更清楚地了解哪些正则表达式模式命中.

【讨论】:

  • 谢谢。这似乎是一种更流畅的方式。不知道你可以命名这些组。
  • 如果您嵌入了捕获组,命名组真的会派上用场。此外,如果模式的数量变得难以处理,您也许可以将所有正则表达式模式变体合并为更少的带有可选项的模式。
【解决方案2】:

试试这个:\s*(season|s)\s*(\d+)(episode|e|x)\s*(\d+)你在第 2 组和第 4 组中的匹配词

import re
p = re.compile(ur'\s*(season|s)\s*(\d+)(episode|e|x)\s*(\d+)', re.MULTILINE)
test_str = u"Hello seinfeld season 01episode 22 foo bar\ns 01e 02\n"

re.findall(p, test_str)

Demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-29
    • 2017-05-13
    • 1970-01-01
    • 2016-02-02
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多