sedを使用して最初の空の行と最後の行の間の行を表示するには?

sedを使用して最初の空の行と最後の行の間の行を表示するには?

シェルスクリプトで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\nUnixで説明したように、ヘッダーに無限の空白行がありません。これはまた、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"
    }
}

おすすめ記事