我正在尝试在shell脚本中解析来自Web服务器的响应。这是响应:
HTTP/1.0 404 NOT FOUND
Content-Length: 223
Content-Type: application/json
Last-Modified: Fri, 21 Aug 2020 15:24:23 GMT
Cache-Control: public, max-age=43200
Expires: Sat, 22 Aug 2020 08:04:19 GMT
ETag: "1598023463.02863-223-4034336499"
Date: Fri, 21 Aug 2020 20:04:19 GMT
Server: Werkzeug/1.0.1 Python/3.8.5
{
"message": {
"status": "404",
"message": "Not Found"
}
}
我将其分配给变量:
% foo="$(curl -i http://127.0.0.1/404)"
我想要一个变量而不是一个变量,以便状态代码和响应正文。抓取状态码很容易:
% echo "$foo" | head -n 1
困难的部分是使用sed筛选出标头。基于布鲁斯·巴内特(Bruce Barnett)精彩的Sed grymoire,我认为这会起作用:
% echo "$foo" | sed '1,/^$/ d'
或者:
% echo "$foo" | sed -n '/^$/,$ p'
但是,这两个命令的结果完全没有。我不明白为什么。
万一重要,我使用的是Homebrew的zsh 5.8和GNU sed 4.8,以及Mac OS的curl 7.64.1。
问题在于curl的输出中有回车符(CR),因此像/^$/
从来没有匹配的模式一样,因为每行都有一个CR,所以它不是空的。
有几件事可以完成,要么删除CR,要么为它们负责。
foo="$(curl -i http://127.0.0.1/404 | tr -d '\r')"
将其删除,然后
printf '%s\n' "$foo" | sed '1,/^$/d'
将正常工作,或者如果我没有使用以下方式删除CR,则可以使用 tr
printf '%s\n' "$foo" | sed $'1,/^\r$/d'
由于zsh可以进行字符串替换,因此我倾向于使用
printf '%s\n' "${foo#*$'\r\n\r\n'}"
或者
printf '%s\n' "${foo#*$'\n\n'}"
取决于我是否曾经tr
剥离过CR,以节省sed进程。
但是有一个警告:命令替换会删除所有结尾的换行符(而不是回车符)。HTTP响应为<header1>CRLF...<headern>CRLFCRLF<body>
。如果<body>
值为空,$foo
则仅包含,<header1>CRLF...<headern>CRLFCR
或者<header1>CRLF...<headern>
如果我们删除了CR ,则将包含。在这些情况下,*$'\r\n\r\n'
或*$'\n\n'
不匹配,并且标头也不会被删除。
在任何情况下,要打印任意字符串后跟换行符,语法为:
printf '%s\n' "$foo" # POSIX
print -r - "$foo" # ksh/zsh
echo -E - "$foo" # zsh
没有 它,如果不能正常工作包含反斜杠(JSON中常见的),或者一些与启动值(不应该是JSON的情况下)。 echo "$foo"
$foo
-
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句