如何使用 sed 顯示第一個空白行和最後一行之間的行?
我正在嘗試在 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 gymoire,我認為這會起作用:
% 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'
or*$'\n\n'
將不匹配,並且標題不會被刪除。在任何情況下,要列印後跟換行符的任意字元串,語法是:
printf '%s\n' "$foo" # POSIX print -r - "$foo" # ksh/zsh echo -E - "$foo" # zsh
如果包含反斜杠(在 json 中很常見)或某些以開頭的值(json 不應該是這種情況) ,則not
echo "$foo"
which 不能正常工作。$foo``-