bash 在两个单独的变量中获取 curl 响应的标题和正文?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25852524/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 11:21:51  来源:igfitidea点击:

Get both the headers and the body of a curl response in two separated variables?

bashcurl

提问by Daniel

I am looking for a way to make ONE curl call and get to variables from it: one with the headers and another with the response body.

我正在寻找一种方法来进行一次 curl 调用并从中获取变量:一个带有标题,另一个带有响应正文。

I've found several questions asking about how to separate headers from body, but people seems only interested in one of them. I need both headers and body.

我发现了几个关于如何将标题与正文分开的问题,但人们似乎只对其中一个感兴趣。我需要标题和正文。

I cannot use an external file to store the body (thus using -o $file is not an option).

我不能使用外部文件来存储正文(因此不能使用 -o $file )。

I can use

我可以用

headers=$(curl -D /dev/stdout $URL)

to get the headers into one variable, but how can I redirect the output to another variable?

将标题放入一个变量中,但如何将输出重定向到另一个变量?

Thanks a lot!

非常感谢!

采纳答案by glenn Hymanman

head=true
while IFS= read -r line; do 
    if $head; then 
        if [[ -z $line ]]; then 
            head=false
        else
            headers+=("$line")
        fi
    else
        body+=("$line")
    fi
done < <(curl -sD - "$url" | sed 's/\r$//')
printf "%s\n" "${headers[@]}"
echo ===
printf "%s\n" "${body[@]}"

To join the elements of an array into a single scalar variable:

要将数组元素连接到单个标量变量中:

the_body=$( IFS=$'\n'; echo "$body[*]" )


In bash4.3, you can use named references to simplify switching from "header" mode to "body" mode:

bash4.3 中,您可以使用命名引用来简化从“header”模式到“body”模式的切换:

declare -n section=headers
while IFS= read -r line; do
    if [[ $line = $'\r' ]]; then
        declare -n section=body
    fi
    section+=("$line")
done < <(curl -sD - "$url")


For some reason, glenn Hymanman's answer did not catch the body part of the response. I had to separate the curl request into another command expansion and then enclose it in double quotes. Then I did not use arrays, but simply concatenated values to the variables. This works for me:

出于某种原因,格伦Hyman曼的回答没有抓住响应的主体部分。我不得不将 curl 请求分成另一个命令扩展,然后用双引号将其括起来。然后我没有使用数组,而是简单地将值连接到变量。这对我有用:

output=$(curl -si -d "" --request POST https://$url)

head=true
while read -r line; do 
    if $head; then 
        if [[ $line = $'\r' ]]; then
            head=false
        else
            header="$header"$'\n'"$line"
        fi
    else
        body="$body"$'\n'"$line"
    fi
done < <(echo "$output")

Thank you, Glenn!

谢谢你,格伦!

回答by 0x10203040

I would like to share a way to parse curl response without any external program, bash only.

我想分享一种无需任何外部程序(仅 bash)即可解析 curl 响应的方法。

First, get the response of a curl request passing -sw "%{http_code}".

首先,获取传递的 curl 请求的响应-sw "%{http_code}"

res=$(curl -sw "%{http_code}" $url)

The result will be a string containing the body followed by the http code.

结果将是一个包含正文后跟 http 代码的字符串。

Then, get the http code:

然后,获取http代码:

http_code="${res:${#res}-3}"

And the body:

还有身体:

if [ ${#res} -eq 3 ]; then
  body=""
else
  body="${res:0:${#res}-3}"
fi

Note that if the length of http_code and response are equal (length 3), body is empty. Else, just strip out the http code and you get the body.

注意,如果 http_code 和 response 的长度相等(长度为 3),则 body 为空。否则,只需去掉 http 代码即可获得正文。