【问题标题】:Curl bash get a header and the body without string manipulationCurl bash 无需字符串操作即可获得标题和正文
【发布时间】:2018-12-05 15:08:13
【问题描述】:

我正在使用 curl 和 bash 从 go cd 获取配置。我需要标有 ETag 的标头,但也需要 json 正文。有没有一种简单的方法可以使用 curl 来做到这一点,还是我必须在 bash 中操作结果?

$ curl 'https://ci.example.com/go/api/admin/pipelines/my_pipeline' \
    -u 'username:password' \
    -H 'Accept: application/vnd.go.cd.v6+json' \
    -i

返回:

HTTP/1.1 200 OK
Content-Type: application/vnd.go.cd.v6+json; charset=utf-8
ETag: "e064ca0fe5d8a39602e19666454b8d77"
{
     "_links": {
     "self": {
             "href": "https://ci.example.com/go/api/admin/pipelines/my_pipeline"
},
"doc": {
  "href": "https://api.gocd.org/#pipeline-config"
},
...

我不能使用 jq 因为它抱怨标题,但我也想要 ETag 标题及其值。

【问题讨论】:

    标签: bash curl jq


    【解决方案1】:

    curl 返回一系列以 CR/LF 结尾的行,最后一行(空行之后)是实际正文。您可以编写一个代码块,首先使用while 循环将标头解析出标准输入,在标头块完成时终止,然后使用jq 读取输入的其余部分。例如:

    # Consume standard input up to, and including, an empty line.
    # Sets global variable 'etag'.
    parse_headers () {
      local header etag_regex='ETag: (.*)'
      while read -d $'\r\n' header; do
        if [[ $header =~ $etag_regex ]]; then
          etag=${BASH_REMATCH[1]}
        elif [[ -z $header ]]; then
          # End of headers
          break
        fi
      done
    }
    
    # Pass input first to parse_headers, then to jq
    {
      parse_headers
      jq '._links.self'  # After parse_headers is done, only the JSON should remain
    } < <(curl ...)
    echo "ETag is $etag"
    

    示例输出

    {
      "href": "https://ci.example.com/go/api/admin/pipelines/my_pipeline"
    }
    ETag is "e064ca0fe5d8a39602e19666454b8d77"
    

    【讨论】:

    • 这会在 jq 更新时将我想要的内容打印到屏幕上。但是 json 颜色是从哪里来的?它如何将 json 打印到屏幕上?到底发生了什么?
    • 如果jq 检测到它的输出是一个终端设备,它就像-C 选项生效一样工作,这意味着它将在其输出中添加转义序列,以便终端解释为颜色-更改说明。如果您不想要彩色输出,请使用 -M 选项禁用它(如果您将输出写入文件,这是默认设置)。
    【解决方案2】:

    也许您应该将响应存储在一个变量中,并使用它来访问 ETag: 标头和 json。

    试试这个:

    response="$(curl -s 'https://ci.example.com/go/api/admin/pipelines/my_pipeline' \
    -u 'username:password' \
    -H 'Accept: application/vnd.go.cd.v6+json' \
    -i)"
    etag_header=$(printf '%s' "${response}" | sed -n '/^ETag.*/ { p }')
    body_json="{${response#*{}"
    
    # use etag_header
    printf "%s\n" "${etag_header}"
    
    # use body_json
    printf "%s\n" "${body_json}" | jq
    

    输出:

    ETag: "e064ca0fe5d8a39602e19666454b8d77"
    {
      "_links": {
        "self": {
          "href": "https://ci.example.com/go/api/admin/pipelines/my_pipeline"    
        }
      },
      "doc": {
        "href": "https://api.gocd.org/#pipeline-config"
      },
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-06
      • 1970-01-01
      • 2017-11-09
      • 2017-04-14
      相关资源
      最近更新 更多