提取URL的host和path需先剥离协议与查询参数,再分别处理IPv6括号和端口;推荐用sed或awk组合实现健壮解析,避免basename/dirname直接作用于完整URL出错。

用 basename 和 dirname 提取路径时要注意协议和端口干扰
直接对完整 URL(如 https://example.com:8080/api/v1/users?id=123)用 basename 或 dirname 会失败,因为它们把 :// 当作普通路径分隔符,结果得到 https: 或空字符串。必须先剥离协议和查询参数。
实操建议:
- 用
sed去掉协议头:sed 's|^[^:]*://||'(匹配开头到://并删掉) - 再用
cut -d'?' -f1去掉查询参数(?id=123部分) - 之后才能安全使用
dirname和basename—— 此时输入已是类似example.com:8080/api/v1/users的格式
主机名提取要区分端口、处理 IPv6 地址
cut -d'/' -f1 看似简单,但遇到 https://[::1]:3000/path 就会把 [::1]:3000 拆成 [::1,漏掉右括号;而 example.com:8080 中的端口是否保留,取决于你的用途。
推荐做法:
- 先用
sed 's|^[^:]*://||; s|/.*$||'提取出 host:port 部分(去掉协议 + 第一个/及之后所有内容) - 对 IPv6 地址,加一层判断:
[[ $hostpart == \[* ]] && host=$(echo "$hostpart" | cut -d']' -f1 | cut -d'[' -f2) - 若需纯域名(去端口),用
cut -d':' -f1,但仅当不含]时才安全——否则先按]切再处理
一行命令组合提取 host 和 path 的可靠写法
把上面逻辑压成可复用的变量赋值,避免临时文件或子 shell 开销:
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
url='https://api.example.com:443/v2/data?x=1' host=$(echo "$url" | sed 's|^[^:]*://||; s|/.*$||' | sed 's|\].*|]|' | cut -d']' -f1 | sed 's|^\[||') path=$(echo "$url" | sed 's|^[^:]*://[^/]*||' | cut -d'?' -f1) # 结果:host=api.example.com:443,path=/v2/data
说明:
- 第一处
sed提取 host:port(含 IPv6 方括号),第二处sed 's|\].*|]|'是为防]:port被误切 -
cut -d'?' -f1必须在提取 path 后立即做,否则查询参数会污染dirname行为 - 如果只要主域名(不要端口),最后再加
| cut -d':' -f1,但注意别加在 IPv6 处理前
用 awk 替代多层 sed 更可控
当 URL 格式较统一(比如已知无 IPv6),awk 单次解析更清晰,也方便扩展字段:
url='http://user:pass@sub.domain.co.uk:8080/a/b/c?d=e'
host=$(echo "$url" | awk -F'[/:?]' '{gsub(/^\[/,"",$3); gsub(/\]$/,"",$3); print $3 ":" $4}' | sed 's/::$/:/')
path=$(echo "$url" | awk -F'[?]' '{print $1}' | awk -F'//' '{print $2}' | awk -F'/' '{for(i=2;i<=NF;i++) printf "/%s", $i; print ""}')关键点:
-
-F'[/:?]'把协议、host、port、path、query 全拆成字段,$3是 host(可能带[),$4是 port - 两次
gsub清洗 IPv6 方括号,sed 's/::$/:/'是为防空 port 导致结尾多冒号 - 路径提取用三次
awk分阶段处理,比单条正则更易调试
真正难的不是切分,而是你得提前想清楚:是否要保留认证信息?是否接受端口缺失时的默认行为?IPv6 地址出现频率高不高?这些决定了该选哪条路。

















