小能豆

Python URL 匹配(正则表达式)

py

我已经尝试匹配以下 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”


阅读 40

收藏
2024-12-08

共1个答案

小能豆

你的正则表达式问题出在对可选部分的处理方式。你在模式中使用了 /*,这会导致正则表达式匹配多个字符(包括斜杠)并消耗掉最后的字母。为了确保正则表达式正确匹配 URL 并允许第二部分(即章节部分)是可选的,首先需要理解你想匹配的两种 URL 格式:

  1. /course/lesson-one/
  2. /course/lesson-one/chapter-one/

你希望第二部分(例如 chapter-one)是可选的,但如果存在,它应该正确匹配。一个可能的解决方案是使用非贪婪匹配和可选分组。

改进的正则表达式:

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

解释:

  1. /course/:匹配字符串 /course/
  2. ([a-zA-Z]+[-a-zA-Z]*):匹配课程部分,允许字母和连字符(如 lesson-one)。
  3. /?:匹配可选的 /,这样就可以确保第二部分是可选的。
  4. ([a-zA-Z]+[-a-zA-Z]*):匹配可选的章节部分(如 chapter-one),同样允许字母和连字符。

注意:

  • /? 表示“零个或一个 /”,这样即使没有 /chapter-one/,也能正确匹配 /course/lesson-one/
  • ([a-zA-Z]+[-a-zA-Z]*) 是对单词和连字符的匹配,确保它可以处理如 lesson-onechapter-one 这样的字符串。
  • 在 URL 为 /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-onecomputers)。
  • match.group(2) 提取章节部分(如 chapter-one),如果没有章节,它会返回 None,并在代码中处理为 'N/A'

通过这种方式,你可以确保无论 URL 中是否包含章节部分,都会得到正确的结果。

2024-12-08