需要掌握的知识点大纲:
本次学习的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[\w\+]+)://
(?:
(?P[^:/]*)
(?::(?P[^@]*))?
@)?
(?:
(?:
\[(?P[^/\?]+)\] |
(?P[^/:\?]+)
)?
(?::(?P[^/\?]*))?
)?
(?:/(?P[^\?]*))?
(?:\?(?P.*))?
""" ,
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'。