为什么可选的正则表达式组(仅)有时为None

时间:2014-08-19 21:27:46

标签: python regex

我在Python中编写一个带有可选部分的正则表达式。我注意到有时这些可选部分与None匹配,有时它们与空字符串匹配,或者至少从我的测试中看起来是这样。我想了解为什么以及如何将正则表达式修改为一致或另一种。

def artifactory_url():
    test_input = [
        "https://www.domain.com/artifactory/my-root",
        "https://www.domain.com/artifactory",
        "https://www.domain.com/artifactory/my-root/platform",
        "http://www.domain.com/artifactory/my-root/platform",
        "http://www.domain.com/artifactory/my-root/platform/Daily Gold Reserve/WW3/bin",
        "single-dir",
        "double/dir",
    ]
    import re
    re_splitroot = re.compile('(?P<drive>https?://.+/artifactory)?/?(?:(?P<root>[^/]+)/?)?(?P<remainder>.*)?/?', re.IGNORECASE)
    for i in test_input:
        dprint (i)
        m = re_splitroot.match(i)
        if m:
            dprint (" True:\n  drive=%s\n  root=%s\n  remainder=%s" % (m.group('drive'), m.group('root'), m.group('remainder')), 0)
        else:
            dprint (" False")

此测试功能产生以下输出。

https://www.domain.com/artifactory/my-root
 True:
  drive=https://www.domain.com/artifactory
  root=my-root
  remainder=
https://www.domain.com/artifactory
 True:
  drive=https://www.domain.com/artifactory
  root=None
  remainder=
https://www.domain.com/artifactory/my-root/platform
 True:
  drive=https://www.domain.com/artifactory
  root=my-root
  remainder=platform
http://www.domain.com/artifactory/my-root/platform
 True:
  drive=http://www.domain.com/artifactory
  root=my-root
  remainder=platform
http://www.domain.com/artifactory/my-root/platform/Daily Gold Reserve/WW3/bin
 True:
  drive=http://www.domain.com/artifactory
  root=my-root
  remainder=platform/Daily Gold Reserve/WW3/bin
single-dir
 True:
  drive=None
  root=single-dir
  remainder=
double/dir
 True:
  drive=None
  root=double
  remainder=dir

1 个答案:

答案 0 :(得分:1)

你的第一部分:

(?P<drive>https?://.+/artifactory)?

应匹配任何http://.../artifactory(如果存在),但尾随?表示如果找不到,则整个捕获的组将为空。

您可能想要使用

(?P<drive>(?:https?://.+/artifactory)?)

这将使该部分捕获&#34;空虚&#34;如果找不到该匹配,但不会将其保留为NULL。

你的第二部分:

(?:(?P<root>[^/]+)\?)?

尝试捕获不是/的任何内容,但其中包含的(?:...)群组有一个尾随?,这也是可选/空的。如果您更换(?P<...>)(?:...)组,您的结果将与第一组更加一致。

最后,你的

(?P<remainder.*)?

组是多余的:它可以仅使用.*捕获0或更多剩余文本,但您也可以选择(?)。您可以删除?,并留下空匹配。

您的示例可以在this page上找到,我建议的更改可以在this one上找到,如果您想查看它们是否会产生任何不同的结果。