我已经尝试将以下网址匹配了几个小时,但似乎无法弄明白并且我非常确定它并不那么困难:
网址可以是:
/course/lesson-one/
或者它也可以是:
/course/lesson-one/chapter-one/
我所拥有的是与第二个网址匹配的以下内容:
/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'
答案 0 :(得分: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'必须属于那里。
答案 1 :(得分: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)
答案 2 :(得分:1)
您可以使用以下正则表达式:
'/course/([a-zA-Z]+[-a-zA-Z]*)(/([a-zA-Z]+[-a-zA-Z]*)/)?'
这使得第二部分可选,并且仍然匹配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)