Bootstrap

URL正则提取各参数

需要掌握的知识点大纲:

  1. 命名捕获组
  2. 选择性匹配(可选分组)
  3. 字符集否定([^…])
  4. 分支结构 (|)
  5. 特殊字符转义
  6. 使用正则表达式解析 URL 和 MySQL 连接字符串

本次学习的pattern:

 (?P<name>[\w\+]+)://       # 1. 匹配协议名称,如 'mysql+',并命名为 'name'
 (?:
     (?P<username>[^:/]*)   # 2. 匹配用户名(不含 ':' 或 '/'),并命名为 'username'
     (?::(?P<password>[^@]*))?  # 3. 可选地匹配冒号后的密码(不含 '@'),并命名为 'password'
 @)?                          # 4. 可选地匹配 '@' 符号,表示用户名和密码的存在
 (?:
     (?:
         \[(?P<ipv6host>[^/\?]+)\]  # 5a. 匹配 IPv6 地址,如 '[2001:db8:abcd::1]',并命名为 'ipv6host'
         |                           # 或
         (?P<ipv4host>[^/:\?]+)     # 5b. 匹配 IPv4 地址,如 '192.168.0.1',并命名为 'ipv4host'
     )?
     (?::(?P<port>[^/\?]*))?     # 6. 可选地匹配冒号后的端口号(不含 '/' 和 '?'),并命名为 'port'
 )?
 (?:/(?P<database>[^\?]*))?   # 7. 可选地匹配斜线后跟的数据库名(不含 '?'),并命名为 'database'
 (?:\?(?P<query>.*))?         # 8. 可选地匹配问号后跟的所有查询参数,并命名为 'query'

案例解说:

pattern = re.compile(
    r"""
        (?P<name>[\w\+]+)://
        (?:
            (?P<username>[^:/]*)
            (?::(?P<password>[^@]*))?
        @)?
        (?:
            (?:
                \[(?P<ipv6host>[^/\?]+)\] |
                (?P<ipv4host>[^/:\?]+)
            )?
            (?::(?P<port>[^/\?]*))?
        )?
        (?:/(?P<database>[^\?]*))?
        (?:\?(?P<query>.*))?
        """,
    re.X,
)

# 示例 MySQL 连接字符串(使用 pymysql)
mysql_url = "mysql+pymysql://user:pass@[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:3306/database?charset=utf8"

# 使用正则表达式匹配并提取数据
match_result = pattern.match(mysql_url)
if match_result:
    name = match_result.group('name')
    username = match_result.group('username')
    password = match_result.group('password')
    ipv6host = match_result.group('ipv6host')
    ipv4host = match_result.group('ipv4host')
    port = match_result.group('port')
    database = match_result.group('database')
    query = match_result.group('query')


# 解析说明:

- `(?P<name>[\w\+]+)://` 匹配类似 'mysql+pymysql://' 的协议部分,并将协议名称捕获为 'name',允许包含字母、数字和 '+' 符号。

- `(?P<username>[^:/]*)` 匹配用户名,不允许包含 ':''/',并命名为 'username'- `(?::(?P<password>[^@]*)?)?@` 匹配可选的密码,密码不能包含 '@',并命名为 'password'。整个密码部分以及 '@' 符号都是可选的。

- `\[(?P<ipv6host>[^/\?]+)\] | (?P<ipv4host>[^/:?]+)` 分别匹配 IPv6 和 IPv4 地址,分别命名为 'ipv6host''ipv4host'。IPv6 地址在方括号内,IPv4 地址为连续的非 '/'':''?' 字符。

- `(?::(?P<port>[^/\?]*))?` 匹配可选的端口号,端口号由非 '/''?' 字符组成,命名为 'port'- `(?:/(?P<database>[^\?]*))?` 匹配可选的数据库名,由非 '?' 字符组成,命名为 'database'- `(?:\?(?P<query>.*))?` 匹配可选的查询字符串,从 '?' 开始到字符串结束,命名为 'query'
;