フル bash
解決。 awk
を必要とせずに他のヘッダーを簡単に解析する方法を示します :
shopt -s extglob # Required to trim whitespace; see below
while IFS=':' read key value; do
# trim whitespace in "value"
value=${value##+([[:space:]])}; value=${value%%+([[:space:]])}
case "$key" in
Server) SERVER="$value"
;;
Content-Type) CT="$value"
;;
HTTP*) read PROTO STATUS MSG <<< "$key{$value:+:$value}"
;;
esac
done < <(curl -sI http://www.google.com)
echo $STATUS
echo $SERVER
echo $CT
プロデュース:
302
GFE/2.0
text/html; charset=UTF-8
RFC-2616 によると、HTTP ヘッダーは 「ARPA インターネット テキスト メッセージのフォーマットの標準」 で説明されているようにモデル化されています。 (RFC822)、セクション 3.1.2 を明確に述べています:
<ブロック引用>field-name は、印刷可能な ASCII 文字 (コロンを除く 10 進数で 33 から 126 の間の値を持つ文字) で構成する必要があります。フィールド本体は、CR または LF を除く任意の ASCII 文字で構成できます。 (CR および/または LF は実際のテキストに存在する場合がありますが、フィールドを展開するアクションによって削除されます。)
したがって、上記のスクリプトは すべき RFC-[2]822 準拠のヘッダーをキャッチ 折りたたみヘッダーの注目すべき例外 .
2 つ以上のヘッダーを抽出したい場合は、すべてのヘッダーを bash 連想配列に詰め込むことができます。これは、特定のヘッダーが 1 回だけ発生することを前提とする単純な関数です。 (Set-Cookie
には使用しないでください);以下を参照してください。)
# Call this as: headers ARRAY URL
headers () {
{
# (Re)define the specified variable as an associative array.
unset $1;
declare -gA $1;
local line rest
# Get the first line, assuming HTTP/1.0 or above. Note that these fields
# have Capitalized names.
IFS=$' \t\n\r' read $1[Proto] $1[Status] rest
# Drop the CR from the message, if there was one.
declare -gA $1[Message]="${rest%$'\r'}"
# Now read the rest of the headers.
while true; do
# Get rid of the trailing CR if there is one.
IFS=$'\r' read line rest;
# Stop when we hit an empty line
if [[ -z $line ]]; then break; fi
# Make sure it looks like a header
# This regex also strips leading and trailing spaces from the value
if [[ $line =~ ^([[:alnum:]_-]+):\ *(( *[^ ]+)*)\ *$ ]]; then
# Force the header to lower case, since headers are case-insensitive,
# and store it into the array
declare -gA $1[${BASH_REMATCH[1],,}]="${BASH_REMATCH[2]}"
else
printf "Ignoring non-header line: %q\n" "$line" >> /dev/stderr
fi
done
} < <(curl -Is "$2")
}
例:
$ headers so http://stackoverflow.com/
$ for h in ${!so[@]}; do printf "%s=%s\n" $h "${so[$h]}"; done | sort
Message=OK
Proto=HTTP/1.1
Status=200
cache-control=public, no-cache="Set-Cookie", max-age=43
content-length=224904
content-type=text/html; charset=utf-8
date=Fri, 25 Jul 2014 17:35:16 GMT
expires=Fri, 25 Jul 2014 17:36:00 GMT
last-modified=Fri, 25 Jul 2014 17:35:00 GMT
set-cookie=prov=205fd7f3-10d4-4197-b03a-252b60df7653; domain=.stackoverflow.com; expires=Fri, 01-Jan-2055 00:00:00 GMT; path=/; HttpOnly
vary=*
x-frame-options=SAMEORIGIN
SO 応答には、Set-Cookie
に 1 つ以上の Cookie が含まれていることに注意してください。 ヘッダーが含まれていますが、単純なスクリプトが同じヘッダー名のエントリを上書きするため、最後のヘッダーしか表示されません。 (たまたま、1 つしかありませんでしたが、それを知ることはできません。)スクリプトを特殊なケース Set-Cookie
に拡張することは可能ですが、 、より良いアプローチはおそらくcookie-jarファイルを提供し、 -b
を使用することです そして -c
それを維持するためのcurlオプション。