シェルスクリプトで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)"
1つの変数ではなく、ステータスコード用の1つの変数と応答本文用の1つの変数が必要です。ステータスコードを取得するのは簡単です。
% echo "$foo" | head -n 1
難しい部分は、sedを使用してヘッダーをフィルタリングすることです。に基づいてブルース・バーネット(Bruce Barnett) 素晴らしい Sed グリモワール、私の考えはこれがうまくいくと思います:
% echo "$foo" | sed '1,/^$/ d'
または:
% echo "$foo" | sed -n '/^$/,$ p'
しかし、両方のコマンドの結果は何もありません。理由がわからない。
重要な場合は、Homebrewのzsh 5.8とGNU sed 4.8を使用し、Mac OSのcurl 7.64.1を使用しています。
答え1
RFC7230では、ヘッダーはCR-LFペア、その後にCRLFペア(CRLF - CRLF)(緩い用語:空行)、HTTPレスポンスの「本文」で区切る必要があります。したがって、通常のhttp/1.1には一部が含まれます。入力する。
\n\n
Unixで説明したように、ヘッダーに無限の空白行がありません。これはまた、sedの場合、aがヘッダーの^$
末尾にある空(DOS)行と一致しないことを意味します。対応する行に\r
(キャリッジリターン)が含まれているためです。 (GNU)sedでこの(ほぼ)空の行を検出する別の方法は次のとおりです^\r$
。
$ printf '%s\n' "$foo" | sed '1,/^\r$/ d'
キャリッジリターンの削除
キャリッジリターンの削除が適用される場合、http応答(サーバーがエクスポートする完全なhttp / 1.1メッセージ)には、\n\n
ヘッダーと本文を区別するために2つの連続する改行()で空白行が含まれます。
そうであれば、特別な値であるnull RS
(awkの短絡モード)がこのヘッダーを処理できます。
$ echo "$foo" | tr -d '\r' | awk -v RS="" 'NR>1'
または、メール本文の空白行を保持するには、次の手順を実行します。
$ echo "$foo" | tr -d '\r' | awk 'BEGIN{ORS=RS="\n\n"}NR>1'
キャリッジリターンを許可
ただし、メッセージ(RFC5322など)とhttp応答(RFC7230などの完全なhttp / 1.1メッセージ)は、次のようにCR NL
使用する必要があります。タイトルの行末タグ。 RSには以下を含めることができます。任意に選択できるキャリッジリターンには正規表現が必要で、定数ではないため、RT(レコードターミネータ)を使用します。これはGNU awkを使用する必要があることを意味します。
$ echo "foo" | awk 'BEGIN{RS="(\r?\n){2}"}NR>1{printf "%s%s",$0,RT}'
{
"message": {
"status": "404",
"message": "Not Found"
}
}
答え2
問題は、カールの出力にキャリッジリターン(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
sedプロセスを保存するためにCRを削除したかどうかによって異なります。
しかし、警告があります:コマンド代替バーみんな末尾の改行文字(キャリッジリターンではない)HTTP応答はです<header1>CRLF...<headern>CRLFCRLF<body>
。<body>
空の場合は、CRが$foo
含まれているか削除されている場合にのみ<header1>CRLF...<headern>CRLFCR
適用されます。<header1>CRLF...<headern>
このような場合、*$'\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"
$foo
-