1

我已经尝试匹配以下 URL 几个小时,但似乎无法弄清楚,我很确定这并不难:

URL 可以是这样的:

/course/lesson-one/

或者也可以是:

/course/lesson-one/chapter-one/

我所拥有的是与第二个 URL 匹配的以下内容:

/course/([a-zA-Z]+[-a-zA-Z]*)/([a-zA-Z]+[-a-zA-Z]*)/

我想要的是第二部分是可选的,但我无法弄清楚我得到的最接近的是以下内容:

/course/([a-zA-Z]+[-a-zA-Z]*)/*([a-zA-Z]+[-a-zA-Z]*)/

但是由于某种原因,上面省略了单词的最后一个字母,例如,如果 URL 是

/course/computers/

我以字符串 'computer' 结尾

4

3 回答 3

1

?如果您需要可选部件,您可以使用。

/course/([a-zA-Z][-a-zA-Z]*)/([a-zA-Z][-a-zA-Z]*/)?
#                                                 ^

(请注意,这[a-zA-Z]+[-a-zA-Z]*等同于[a-zA-Z][-a-zA-Z]*。)

使用额外的分组从匹配(?:…)中排除/,同时允许多个元素一次是可选的:

/course/([a-zA-Z][-a-zA-Z]*)/(?:([a-zA-Z][-a-zA-Z]*)/)?
#                            ~~~                     ~^

您的第二个正则表达式吞下了最后一个字符,因为:

  /course/([a-zA-Z]+[-a-zA-Z]*)/*([a-zA-Z]+[-a-zA-Z]*)/
          ^^^^^^^^^^^^^^^^^^^^^  ~~~~~~~~~~~~~~~~~~~~~
        this matches 'computer'  and this matches the 's'.

由于 ,此正则表达式中的第二组需要匹配一些长度为 1 或更多的字母+,因此 's' 必须属于那里。

于 2013-05-08T20:27:18.540 回答
1

用一个 ”?” 在某些事情使它被认为是可选的之后。

>>> r = r"/course/([a-zA-Z]+[-a-zA-Z]*)(/[A-Z[a-z]+[-a-zA-Z]*)?"
>>> s = "/course/lesson-one/chapter-one/"
>>> re.match(r, s).groups()
('lesson-one', '/chapter-one')
>>> s = "/course/computers/"
>>> re.match(r, s).groups()
('computers', None)
于 2013-05-08T20:28:08.807 回答
1

您可以使用以下正则表达式:

'/course/([a-zA-Z]+[-a-zA-Z]*)(/([a-zA-Z]+[-a-zA-Z]*)/)?'

这使得第二部分是可选的,并且仍然匹配 URL 的每个部分。

请注意,URL 的第二部分有两组:一组匹配/chapter-one/,一组匹配chapter-one

>>> re.match('/course/([a-zA-Z]+[-a-zA-Z]*)(/([a-zA-Z]+[-a-zA-Z]*)/)?', '/course/lesson-one/chapter-one/').groups()
('lesson-one', '/chapter-one/', 'chapter-one')

相似地:

>>> re.match('/course/([a-zA-Z]+[-a-zA-Z]*)(/([a-zA-Z]+[-a-zA-Z]*)/)?', '/course/lesson-one/').groups()
('lesson-one', None, None)
于 2013-05-08T20:29:06.453 回答