curl
命令输出格式化指南:精炼信息,掌控结果
curl
是一个功能强大的命令行工具,用于传输数据,支持多种协议(如 HTTP, HTTPS, FTP, FTPS, SCP, SFTP, TFTP, DICT, TELNET, LDAP, LDAPS, GOPHER, FILE, RTMP, RTSP, POP3, POP3S, SMTP, SMTPS, IMAP, IMAPS, SMB, SMBS)。它广泛应用于网络调试、自动化脚本、数据下载等场景。
然而,curl
的默认输出有时可能包含大量信息,如进度条、连接详情、下载数据等,这对于自动化处理或只关注特定信息的场景来说显得过于冗余。幸运的是,curl
提供了丰富的选项来控制其输出,让用户能够精确地获取所需信息,并以易于解析或阅读的格式呈现。
本文将深入探讨 curl
的输出格式化技巧,从基础的静默输出到高级的自定义信息提取,帮助您更好地利用 curl
。
1. 理解 curl
的默认输出
在深入格式化之前,先了解 curl
的默认输出构成是很重要的。通常,一个简单的 curl <URL>
命令会输出:
- 下载进度条 (Progress Meter): 显示下载的速度、已下载量、剩余时间等。
- 错误或状态信息: 在进度条下方或完成后显示,如连接错误、重定向信息等。
- 响应体 (Response Body): 这是最重要的部分,即从服务器获取的数据内容(如网页HTML、JSON数据、文件内容等)。
例如:
bash
curl https://www.example.com
输出可能包含:
“`
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 –:–:– –:–:– –:–:– 0
100 1270 100 1270 0 0 2152 0 –:–:– –:–:– –:–:– 2152
… (网页HTML内容) …
“`
这个默认输出对于交互式使用很友好,但如果要在脚本中只获取 HTML 内容,或者只关心 HTTP 状态码,这些附加信息就变成了干扰。
2. 控制输出的显示级别:静默与详细
curl
提供了控制输出详细程度的基本选项:
2.1 静默模式 (-s
, --silent
)
-s
或 --silent
选项会完全抑制 curl
的进度条和错误消息(大多数情况下)。这是在脚本中获取纯净响应体最常用的选项。
bash
curl -s https://www.example.com
输出将只有响应体:
“`html
… (网页HTML内容) …
“`
注意: -s
会抑制 大多数 错误消息。如果发生严重的连接错误、DNS查找失败等,它可能仍然会输出一些信息到标准错误 (stderr)。如果需要完全静默,甚至包括错误信息,可以重定向 stderr 到 /dev/null
(或 Windows 上的 NUL
)。
2.2 显示错误但静默进度条 (-S
, --show-error
)
当使用 -s
时,如果请求失败,您可能看不到任何错误信息,这使得调试变得困难。-S
或 --show-error
选项通常与 -s
结合使用。它会在使用 -s
时强制 curl
显示错误信息。
“`bash
尝试访问一个不存在的域名,并显示错误
curl -s -S http://this.domain.does.not.exist
“`
输出可能类似:
curl: (6) Could not resolve host: this.domain.does.not.exist
如果没有 -S
,在某些情况下,这个错误可能不会显示。
2.3 冗余模式 (-v
, --verbose
)
与静默模式相反,-v
或 --verbose
选项会输出非常详细的调试信息到标准错误 (stderr)。这些信息包括:
- 试图连接的IP地址和端口
- SSL/TLS握手详情
- 发送的请求头
- 接收到的响应头
- 连接状态和数据传输过程
这对于诊断连接问题、查看请求和响应头、理解重定向过程等非常有用。
bash
curl -v https://www.example.com
输出会包含大量以 *
, >
, <
开头的调试信息(分别表示连接信息、发送的请求头、接收的响应头),最后才是响应体。
“`
* Trying 93.184.216.34:443…
* Connected to www.example.com (93.184.216.34) port 443 (#0)
* ALPN: offers h2
* ALPN: offers http/1.1
* … (SSL/TLS handshake details) …
GET / HTTP/1.1
Host: www.example.com
User-Agent: curl/7.81.0
Accept: /< HTTP/1.1 200 OK
< Age: 500000
< Cache-Control: max-age=604800
< Content-Type: text/html; charset=UTF-8
< Date: Thu, 25 Jan 2024 10:00:00 GMT
< Etag: “3147526947+ident”
< Expires: Thu, 01 Feb 2024 10:00:00 GMT
< Last-Modified: Tue, 02 Jan 2024 15:00:00 GMT
< Server: ECS (sec/9300)
< Vary: Accept-Encoding
< X-Cache: HIT
< Content-Length: 1270
<
{ [1270 bytes data]
… (网页HTML内容) …
- Connection #0 to host www.example.com left intact
“`
curl -v
是调试网络请求时不可或缺的工具。请注意,调试信息是输出到标准错误流 (stderr) 的,而响应体是输出到标准输出流 (stdout) 的。这使得您可以使用重定向来分离它们,例如 curl -v example.com > body.html 2> debug.log
。
3. 控制输出的内容:响应头与响应体
除了控制详细程度,您还可以选择 curl
应该输出哪些部分:响应头、响应体,或者两者。
3.1 只显示响应头 (-I
, --head
)
-I
或 --head
选项会发送一个 HEAD
请求给服务器(而不是默认的 GET
)。服务器通常只会返回响应头,而不包含响应体。这是一种快速检查网页是否存在、获取文件大小、查看缓存信息或重定向目标的方式。
bash
curl -I https://www.example.com
输出将只包含响应头:
HTTP/1.1 200 OK
Age: 500000
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Thu, 25 Jan 2024 10:00:00 GMT
Etag: "3147526947+ident"
Expires: Thu, 01 Feb 2024 10:00:00 GMT
Last-Modified: Tue, 02 Jan 2024 15:00:00 GMT
Server: ECS (sec/9300)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1270
注意: 虽然 -I
发送的是 HEAD 请求,但并非所有服务器都完全支持 HEAD 请求,或者其 HEAD 响应头可能与 GET 请求的响应头略有不同。
3.2 包含响应头和响应体 (-i
, --include
)
-i
或 --include
选项会在输出响应体之前,先输出完整的响应头。与 -v
不同,-i
只输出响应头,不包含连接过程或请求头等其他调试信息。
bash
curl -i https://www.example.com
输出将包含响应头,然后是响应体:
“`
HTTP/1.1 200 OK
Age: 500000
Cache-Control: max-age=604800
Content-Type: text/html; charset=UTF-8
Date: Thu, 25 Jan 2024 10:00:00 GMT
Etag: “3147526947+ident”
Expires: Thu, 01 Feb 2024 10:00:00 GMT
Last-Modified: Tue, 02 Jan 2024 15:00:00 GMT
Server: ECS (sec/9300)
Vary: Accept-Encoding
X-Cache: HIT
Content-Length: 1270
… (网页HTML内容) …
“`
这在需要同时查看服务器响应状态、内容类型、缓存策略等信息,并获取响应体时很有用。
4. 控制输出的目标:标准输出与文件
默认情况下,curl
将响应体输出到标准输出 (stdout)。您可以将其重定向到文件。
4.1 将输出保存到文件 (-o
, --output
)
-o <file>
或 --output <file>
选项将响应体保存到指定的文件中,而不是打印到标准输出。这对于下载文件或将网页内容保存到本地非常有用。
bash
curl -o example.html https://www.example.com
这将把 https://www.example.com
的 HTML 内容保存到当前目录下的 example.html
文件中。
您可以结合 -s
使用,以避免在下载过程中看到进度条:
bash
curl -s -o example.html https://www.example.com
4.2 使用远程文件名保存 (-O
, --remote-name
)
-O
或 --remote-name
选项会尝试根据远程 URL 的文件名部分或 Content-Disposition
响应头来确定本地保存的文件名。这在下载已知文件名但不想手动指定时很方便。
bash
curl -O https://example.com/path/to/data.zip
这将尝试将文件保存为 data.zip
。
bash
curl -O https://example.com/somefile.php?id=123 # 可能会保存为 somefile.php
4.3 丢弃响应体
如果您只关心响应头或使用 -w
选项获取的元信息,而不需要响应体,可以将响应体重定向到“空设备”:
- Linux/macOS:
curl ... -o /dev/null
- Windows:
curl ... -o NUL
“`bash
只检查状态码和下载时间,不保存或显示响应体
curl -s -w “Status: %{http_code}, Time: %{time_total}s\n” -o /dev/null https://www.example.com
“`
5. 高级格式化:使用 -w
(write out)
-w <format_string>
或 --write-out <format_string>
是 curl
中最强大的输出格式化选项。它允许您在请求完成后,以高度自定义的格式输出关于传输的信息,如 HTTP 状态码、下载速度、总时间、文件大小等等。
-w
选项的参数是一个格式字符串,其中包含文本和以 %{variable_name}
形式表示的特殊变量。curl
会在完成传输后解析这个字符串,用实际的值替换变量,并将其输出到标准输出 (stdout)。
5.1 -w
的基本用法
bash
curl -w "HTTP Status: %{http_code}\n" https://www.example.com
这个命令会先执行请求,然后输出:
“`
… (响应体) …
HTTP Status: 200
“`
请注意,默认情况下,`-w` 的输出会跟在响应体之后。为了只输出 `-w` 的内容而不显示响应体,通常需要结合 `-s` 和 `-o /dev/null` (或 NUL)。
“`bash
curl -s -o /dev/null -w “HTTP Status: %{http_code}\n” https://www.example.com
“`
输出将只包含:
“`
HTTP Status: 200
“`
### 5.2 常用的 `-w` 变量
`-w` 提供了大量变量,以下是一些最常用和最有用的:
* `%{http_code}` 或 `%{response_code}`: HTTP 状态码(如 200, 404, 500)。
* `%{time_total}`: 整个传输过程的总时间(秒),从开始到结束,包括名称解析、连接、传输等所有阶段。
* `%{time_connect}`: 从开始到连接建立完成的时间(秒)。
* `%{time_starttransfer}`: 从开始到第一个字节数据传输完成的时间(秒)。
* `%{time_namelookup}`: 名称解析所需的时间(秒)。
* `%{time_pretransfer}`: 从开始到文件传输即将开始的时间(秒),包括名称解析、连接、SSL握手等。
* `%{time_redirect}`: 所有重定向步骤所花费的总时间(秒)。
* `%{speed_download}`: 平均下载速度(字节/秒)。
* `%{speed_upload}`: 平均上传速度(字节/秒)。
* `%{size_download}`: 下载的总字节数。
* `%{size_upload}`: 上传的总字节数。
* `%{url_effective}`: 如果发生重定向,这是最终有效请求的URL。否则是原始URL。
* `%{num_connects}`: 请求过程中建立的连接数。
* `%{num_redirects}`: 请求过程中发生的重定向次数。
* `%{remote_ip}`: 连接到的远程服务器IP地址。
* `%{remote_port}`: 连接到的远程服务器端口。
* `%{local_ip}`: 本地用于连接的IP地址。
* `%{local_port}`: 本地用于连接的端口。
* `%{errormsg}`: 如果发生错误,这是错误的详细描述。
* `%{content_type}`: 响应的 Content-Type 头字段的值。
* `%{num_of_shields_up}`: (玩笑变量,没有实际意义,只是展示可以自定义文本)
您可以在格式字符串中组合这些变量以及普通文本、空格、换行符 (`\n`)、制表符 (`\t`) 等。
### 5.3 `-w` 格式字符串示例
更复杂的例子:
“`bash
curl -s -o /dev/null -w “URL: %{url_effective}\nStatus: %{http_code}\nTotal Time: %{time_total}s\nDownload Speed: %{speed_download} B/s\nSize: %{size_download} bytes\n” https://www.example.com
“`
可能的输出:
“`
URL: https://www.example.com/
Status: 200
Total Time: 0.123456s
Download Speed: 10240 B/s
Size: 1270 bytes
“`
**使用 `-w` 从文件读取格式字符串 (`-w @
如果格式字符串很长或您想重用它,可以将其保存在一个文件中,然后使用 `-w @
创建一个格式文件 (e.g., `curl_format.txt`):
“`
URL: %{url_effective}
Status: %{http_code}
Total Time: %{time_total}s
Speed: %{speed_download} B/s
Size: %{size_download} bytes
Content-Type: %{content_type}
Remote IP: %{remote_ip}
“`
然后使用:
“`bash
curl -s -o /dev/null -w “@curl_format.txt” https://www.example.com
“`
输出将按照文件的格式显示信息。
**`-w` 中的特殊字符和转义**
在 `-w` 格式字符串中,您可以使用标准 C 语言风格的转义序列,如 `\n` (换行)、`\r` (回车)、`\t` (制表符)。
如果您需要在格式字符串中包含百分号 `%` 或大括号 `{}`,并且它们不是变量的一部分,可能需要进行转义。通常,单个 `%` 可以通过 `%%` 来输出。对于 `{}`,只要它们不构成 `%{variable_name}` 的形式,通常可以直接使用。如果确实需要输出字面的 `%{}` 结构,并且可能被误认为变量,复杂的场景可能需要查阅文档或通过间接方式实现。
**`%{variable_name}` 中的修饰符**
一些变量(如 `%{http_code}`, `%{time_total}`)支持修饰符。例如,`%{http_code}` 可以是 `%{http_code}` (原始数值) 或 `%{http_code_str}` (带有文本描述,但这个变量不太常用,且描述不总是可用)。更常见的用法是 `%escape{…}`,用于对变量的值进行 URL 或 shell 安全的转义。
例如,如果 `%{url_effective}` 包含特殊字符,可以使用 `%escape{url_effective}` 进行转义。但对于大多数性能或状态信息,直接使用变量名即可。
### 5.4 `-w` 的使用场景
`-w` 选项非常适合以下场景:
* **性能监控:** 快速获取请求的总时间、连接时间、下载速度等指标。
* **状态检查:** 仅获取 HTTP 状态码来判断请求是否成功。
* **自动化脚本:** 提取特定信息(如最终 URL、内容类型)供脚本进一步处理。
* **简单的 API 测试:** 验证响应状态码或内容类型。
**重要提示:** `-w` 的输出总是发送到标准输出 (stdout),这与 `-v` 的调试信息(发送到 stderr)不同。这使得您可以轻松地将 `-w` 的输出通过管道传递给其他命令进行处理,或者将其重定向到文件,同时将响应体丢弃或保存到另一个地方。
## 6. 处理特定数据类型(JSON, XML 等)
`curl` 主要负责数据传输。它会按原样输出接收到的响应体。对于结构化数据(如 JSON 或 XML),`curl` 不会自带解析或美化功能。您需要将 `curl` 的输出通过管道传递给专门处理这些格式的工具。
### 6.1 处理 JSON 输出
常用的 JSON 处理工具是 `jq`。它可以解析 JSON 数据,并提供查询、过滤、转换等功能。
**获取并美化 JSON 输出:**
“`bash
curl -s https://api.example.com/data | jq .
“`
这里的 `jq .` 表示解析输入 JSON 并原样输出,通常会进行缩进和颜色高亮(如果终端支持)。
**提取 JSON 中的特定字段:**
假设 API 返回 `{ “name”: “Alice”, “age”: 30 }`,您只想获取 `name` 字段:
“`bash
curl -s https://api.example.com/data | jq -r ‘.name’
“`
`-r` 选项表示输出原始字符串值(不带引号)。
### 6.2 处理 XML 输出
常用的 XML 处理工具是 `xmllint`(libxml2 包的一部分)或 `xsltproc`。
**获取并美化 XML 输出:**
“`bash
curl -s https://www.w3schools.com/xml/note.xml | xmllint –format –
“`
`–format -` 表示从标准输入读取 XML 并格式化输出。
**提取 XML 中的特定元素:**
使用 `xpath` 功能(需要安装 `xmlstarlet` 或类似工具):
“`bash
curl -s https://www.w3schools.com/xml/note.xml | xmlstarlet sel -t -v “//body”
“`
这将提取 `