在 cURL 中处理 URL 编码和特殊字符是常见需求,特别是在发送包含空格、中文或特殊符号的数据时。正确编码能确保请求被正确解析。
URL 编码基础
URL 编码(Percent Encoding)将特殊字符转换为 %XX 格式,其中 XX 是字符的十六进制 ASCII 码。
bash# 需要编码的常见字符 空格 -> %20 或 + & -> %26 = -> %3D ? -> %3F # -> %23 % -> %25 中文 -> %E4%B8%AD%E6%96%87
cURL 的编码方式
1. --data-urlencode 自动编码
bash# 自动对数据进行 URL 编码 curl -X POST https://api.example.com/search \ --data-urlencode "query=hello world" # 结果:query=hello%20world # 编码特殊字符 curl -X POST https://api.example.com/search \ --data-urlencode "query=foo&bar=baz" # 结果:query=foo%26bar%3Dbaz # 编码中文字符 curl -X POST https://api.example.com/search \ --data-urlencode "query=中文搜索" # 结果:query=%E4%B8%AD%E6%96%87%E6%90%9C%E7%B4%A2
2. 手动编码
bash# 使用 printf 进行编码 ENCODED=$(printf '%s' 'hello world' | od -An -tx1 | tr -d ' \n' | sed 's/../%&/g') curl -X POST -d "query=$ENCODED" https://api.example.com/search # 使用 Python 编码 ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('hello world'))") curl -X POST -d "query=$ENCODED" https://api.example.com/search # 使用 jq 编码 ENCODED=$(jq -nr --arg s 'hello world' '$s|@uri') curl -X POST -d "query=$ENCODED" https://api.example.com/search
URL 中的特殊字符处理
查询参数中的特殊字符
bash# 错误方式:& 会被解释为参数分隔符 curl "https://api.example.com/search?q=foo&bar=baz" # 实际发送两个参数:q=foo 和 bar=baz # 正确方式:手动编码 curl "https://api.example.com/search?q=foo%26bar%3Dbaz" # 或使用 --data-urlencode(自动处理 &) curl -G https://api.example.com/search \ --data-urlencode "q=foo&bar=baz"
路径中的特殊字符
bash# 路径中包含空格 curl "https://api.example.com/files/my%20document.pdf" # 路径中包含中文 curl "https://api.example.com/files/%E4%B8%AD%E6%96%87%E6%96%87%E4%BB%B6.pdf" # 使用 --path-as-is 保留特殊路径 curl --path-as-is "https://api.example.com/../secret.txt"
不同场景的处理方式
场景 1:表单数据提交
bash# 使用 --data-urlencode 自动编码表单数据 curl -X POST https://api.example.com/submit \ --data-urlencode "name=张三" \ --data-urlencode "email=zhangsan@example.com" \ --data-urlencode "message=Hello World! 你好世界!" # 混合使用编码和非编码数据 curl -X POST https://api.example.com/submit \ -d "id=123" \ --data-urlencode "content=Special chars: & = ?"
场景 2:URL 查询参数
bash# 使用 -G 和 --data-urlencode 构建查询字符串 curl -G https://api.example.com/search \ --data-urlencode "q=hello world" \ --data-urlencode "category=技术&编程" \ --data-urlencode "page=1" # 结果 URL: # https://api.example.com/search?q=hello%20world&category=%E6%8A%80%E6%9C%AF%26%E7%BC%96%E7%A8%8B&page=1
场景 3:JSON 数据中的特殊字符
bash# JSON 中的特殊字符需要转义 curl -X POST https://api.example.com/users \ -H "Content-Type: application/json" \ -d '{"name":"张三","bio":"Line1\nLine2\tTabbed"}' # 使用 jq 处理复杂 JSON jq -n '{name: "张三", bio: "Line1\nLine2"}' | \ curl -X POST https://api.example.com/users \ -H "Content-Type: application/json" \ -d @-
编码工具函数
bash# URL 编码函数 url_encode() { local string="$1" local encoded="" local pos c o for (( pos=0; pos<${#string}; pos++ )); do c=${string:$pos:1} case "$c" in [-_.~a-zA-Z0-9]) encoded+="$c" ;; *) printf -v o '%%%02x' "'$c"; encoded+="$o" ;; esac done echo "$encoded" } # 使用示例 QUERY=$(url_encode "hello world & more") curl "https://api.example.com/search?q=$QUERY"
常见编码问题
bash# 问题 1:空格被错误处理 # 错误: curl "https://api.example.com/search?q=hello world" # 正确: curl "https://api.example.com/search?q=hello%20world" # 问题 2:& 符号被解释为分隔符 # 错误: curl "https://api.example.com/search?q=A&B" # 正确: curl "https://api.example.com/search?q=A%26B" # 问题 3:中文乱码 # 错误: curl "https://api.example.com/search?q=中文" # 正确: curl "https://api.example.com/search?q=%E4%B8%AD%E6%96%87"
完整示例脚本
bash#!/bin/bash # URL 编码处理示例 API_BASE="https://api.example.com/v1" # 编码函数 urlencode() { python3 -c "import urllib.parse; print(urllib.parse.quote('''$1'''))" } # 搜索请求 search_query="hello world & special chars: 中文" encoded_query=$(urlencode "$search_query") echo "Original: $search_query" echo "Encoded: $encoded_query" # 发送请求 curl -G "${API_BASE}/search" \ --data-urlencode "q=$search_query" \ -H "Accept: application/json" # 表单提交 form_data="name=张三&email=test@example.com&msg=Hello World!" curl -X POST "${API_BASE}/submit" \ --data-urlencode "name=张三" \ --data-urlencode "email=test@example.com" \ --data-urlencode "msg=Hello World!"
最佳实践
- 优先使用
--data-urlencode:自动处理编码,避免错误 - 查询参数使用
-G:配合--data-urlencode构建 URL - JSON 使用工具生成:用
jq处理复杂 JSON,自动转义 - 避免手动拼接 URL:容易遗漏编码,导致请求失败
- 测试编码结果:使用
-v查看实际发送的 URL