我已经尝试匹配以下 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”
你的正则表达式问题出在对可选部分的处理方式。你在模式中使用了 /*
,这会导致正则表达式匹配多个字符(包括斜杠)并消耗掉最后的字母。为了确保正则表达式正确匹配 URL 并允许第二部分(即章节部分)是可选的,首先需要理解你想匹配的两种 URL 格式:
/course/lesson-one/
/course/lesson-one/chapter-one/
你希望第二部分(例如 chapter-one
)是可选的,但如果存在,它应该正确匹配。一个可能的解决方案是使用非贪婪匹配和可选分组。
/course/([a-zA-Z]+[-a-zA-Z]*)/?([a-zA-Z]+[-a-zA-Z]*)/
/course/
:匹配字符串 /course/
。([a-zA-Z]+[-a-zA-Z]*)
:匹配课程部分,允许字母和连字符(如 lesson-one
)。/?
:匹配可选的 /
,这样就可以确保第二部分是可选的。([a-zA-Z]+[-a-zA-Z]*)
:匹配可选的章节部分(如 chapter-one
),同样允许字母和连字符。/?
表示“零个或一个 /
”,这样即使没有 /chapter-one/
,也能正确匹配 /course/lesson-one/
。([a-zA-Z]+[-a-zA-Z]*)
是对单词和连字符的匹配,确保它可以处理如 lesson-one
和 chapter-one
这样的字符串。/course/lesson-one/
时,第二个捕获组会为空。import re
# 正则表达式
pattern = r"/course/([a-zA-Z]+[-a-zA-Z]*)/?([a-zA-Z]+[-a-zA-Z]*)/"
# 测试 URLs
urls = [
"/course/lesson-one/",
"/course/lesson-one/chapter-one/",
"/course/computers/"
]
# 匹配
for url in urls:
match = re.match(pattern, url)
if match:
print(f"URL: {url}")
print(f"Course: {match.group(1)}")
print(f"Chapter: {match.group(2) if match.group(2) else 'N/A'}\n")
else:
print(f"URL: {url} did not match.\n")
URL: /course/lesson-one/
Course: lesson-one
Chapter: N/A
URL: /course/lesson-one/chapter-one/
Course: lesson-one
Chapter: chapter-one
URL: /course/computers/
Course: computers
Chapter: N/A
match.group(1)
将提取课程部分(如 lesson-one
或 computers
)。match.group(2)
提取章节部分(如 chapter-one
),如果没有章节,它会返回 None
,并在代码中处理为 'N/A'
。通过这种方式,你可以确保无论 URL 中是否包含章节部分,都会得到正确的结果。