如何通过 /bin/sh 解析 HTTP headers?
How to parse HTTP headers by /bin/sh?
这里 - 在 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
但是如何将其转换为纯 sh?
我也打算使用 wget 而不是 curl,但似乎我可以处理。
如果你没有 extglob
,你可以 trim 空格
set -- $value
value=$*
这也会压缩字段内部的空白,但在这种情况下似乎无害。它还将执行通配符扩展,这是一个更讨厌的问题; set -f
可以解决这个问题,如果你可以使用的话。
但是,也许最简单的解决方案是通过管道传输到分配变量的简单 Awk 脚本,这样您就可以 eval
它们。
eval $(curl -sI http://www.google.com |
awk -v q="'" '{ gsub(/\r/, ""); gsub(q, q "\"" q "\"" q); }
/HTTP\// { print "PROTO=" q q;
print "STATUS=" q q; print "MSG=" q q; next }
/^Server: / { ="SERVER=" q; $NF = $NF q; sub(q " ", q); print; next; }
/^Content-Type: / { ="CT=" q; $NF = $NF q; sub(q " ", q); print; next; }')
单引号应该足以确保 eval
是安全的,尽管我确信空格处理可能更可靠。
这是用 heirloom-sh 测试的。它应该适用于您找到的任何 bourne shell:
(curl -I -s http://www.example.com;echo)| (
read HTTP_VAR_PROTO HTTP_VAR_STATUS HTTP_VAR_MSG
while IFS=': ' read -r key value; do
case "$key" in
Server) HTTP_VAR_SERVER="$value"
;;
Content-Type) HTTP_VAR_CONTENT_TYPE="$value"
;;
'')
set #remove "set" and put your script here
;;
esac
done
)
我在设置变量前加上 HTTP_VAR_
前缀,以避免让 HTTP 响应覆盖环境的重要部分。你必须把你的脚本 inside case
,但没有办法(不使用外部程序或 eval
ing 输入)得到 read
在 bog-standard bourne 中以你想要的方式工作。
您可以 trim 空格,方法是在此处文档中使用 read
。使用命名管道 "simulate" 进程替换。 (进程替换实际上可以在某些操作系统上使用命名管道实现。)
mkfifo headers
curl -sI http://www.google.com > headers &
{
# This line is guaranteed to be first, before any headers.
# Read it separately.
read -r PROTO STATUS MSG
while IFS=':' read -r key value; do
# trim whitespace in "value"
read -r value <<EOF
$value
EOF
case $key in
Server) SERVER="$value"
;;
Content-Type) CT="$value"
;;
esac
done
} < headers
rm headers
我把它留作练习,研究如何正确缩进此处文档的正文。
这里 - 在 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
但是如何将其转换为纯 sh?
我也打算使用 wget 而不是 curl,但似乎我可以处理。
如果你没有 extglob
,你可以 trim 空格
set -- $value
value=$*
这也会压缩字段内部的空白,但在这种情况下似乎无害。它还将执行通配符扩展,这是一个更讨厌的问题; set -f
可以解决这个问题,如果你可以使用的话。
但是,也许最简单的解决方案是通过管道传输到分配变量的简单 Awk 脚本,这样您就可以 eval
它们。
eval $(curl -sI http://www.google.com |
awk -v q="'" '{ gsub(/\r/, ""); gsub(q, q "\"" q "\"" q); }
/HTTP\// { print "PROTO=" q q;
print "STATUS=" q q; print "MSG=" q q; next }
/^Server: / { ="SERVER=" q; $NF = $NF q; sub(q " ", q); print; next; }
/^Content-Type: / { ="CT=" q; $NF = $NF q; sub(q " ", q); print; next; }')
单引号应该足以确保 eval
是安全的,尽管我确信空格处理可能更可靠。
这是用 heirloom-sh 测试的。它应该适用于您找到的任何 bourne shell:
(curl -I -s http://www.example.com;echo)| (
read HTTP_VAR_PROTO HTTP_VAR_STATUS HTTP_VAR_MSG
while IFS=': ' read -r key value; do
case "$key" in
Server) HTTP_VAR_SERVER="$value"
;;
Content-Type) HTTP_VAR_CONTENT_TYPE="$value"
;;
'')
set #remove "set" and put your script here
;;
esac
done
)
我在设置变量前加上 HTTP_VAR_
前缀,以避免让 HTTP 响应覆盖环境的重要部分。你必须把你的脚本 inside case
,但没有办法(不使用外部程序或 eval
ing 输入)得到 read
在 bog-standard bourne 中以你想要的方式工作。
您可以 trim 空格,方法是在此处文档中使用 read
。使用命名管道 "simulate" 进程替换。 (进程替换实际上可以在某些操作系统上使用命名管道实现。)
mkfifo headers
curl -sI http://www.google.com > headers &
{
# This line is guaranteed to be first, before any headers.
# Read it separately.
read -r PROTO STATUS MSG
while IFS=':' read -r key value; do
# trim whitespace in "value"
read -r value <<EOF
$value
EOF
case $key in
Server) SERVER="$value"
;;
Content-Type) CT="$value"
;;
esac
done
} < headers
rm headers
我把它留作练习,研究如何正确缩进此处文档的正文。