bash で URL をパースして連想配列に代入する
1年くらい前にこんなのを作っていたのですけど、これはちょいと使い勝手が良くない気がしました。抜き出したい部分が増えるたびに新しいシェル変数が必要です。
これは楽しくないので、パースした結果を連想配列に入れるように作り変えてみました。
連想配列は bash 4.x 以降が必要です。正規表現を使えばもっと短いコードで済むわけですが、あえて正規表現なしでやってみるとやはり大変でした。
#!/bin/bash declare -A url_parse_array url_parse_array=( ["scheme"]="" ["uid"]="" ["pass"]="" ["hostname"]="" ["port"]="" ["resource"]="" ["query"]="" ["fragment"]="" ) parse_url() { # URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] # hier-part = "//" authority path-abempty # / path-absolute # / path-rootless # / path-empty # authority = [ userinfo "@" ] host [ ":" port ] # userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) # host = IP-literal / IPv4address / reg-name # port = *DIGIT local target=$1 # scheme # 最初の : より前の部分を抜いている # scheme://userinfo@host:port/path?query#fragment # -> scheme url_parse_array["scheme"]=${target%%:*} # uid:pass を抜く # まずは // より後ろの文字列を抜く # scheme://userinfo@host:port/path?query#fragment # -> userinfo@host:port/path?query#fragment local uid_url=${target#*//} # 次に @ より前の部分を抜く。これに該当する文字列は UID:PASS のはず。 # userinfo@host:port/path?query#fragment # -> userinfo local uid_pass=${uid_url%%@*} # URL から authority (ホスト名、ポート、パスのかたまり)を抜く # @ 以降の文字がこれに該当する。 # userinfo@host:port/path?query#fragment # -> host:port/path?query#fragment local authority=${uid_url#*@} # host:port/path?query#fragment # -> path?query#fragment local hierpart_query_fragment=${authority#*/} local hierpart_query=${hierpart_query_fragment%#*} url_parse_array["hierpart"]=${hierpart_query%\?*} local query_fragment=${hierpart_query_fragment#*\?} local fragment=${hierpart_query_fragment#*\#} local query if [ "${fragment}" == "${hierpart_query_fragment}" ]; then url_parse_array["fragment"]="" query=${hierpart_query_fragment#*\?} if [ "${query}" != "${url_parse_array['hierpart']}" ] ; then url_parse_array["query"]=${query} elif [ "${query}" != "${query_fragment}" ]; then url_parse_array["query"]=${query} fi else url_parse_array["fragment"]=${fragment} query=${query_fragment%#*} if [ "${query}" != "${url_parse_array['hierpart']}" ]; then url_parse_array["query"]=${query} fi fi # uid:pass から uid を抜く local uid=${uid_pass%%:*} if [ "$uid" != "$authority" ]; then url_parse_array["uid"]=${uid} fi local pass=${uid_pass##*:} # uid:pass から pass を抜く if [ "$uid" != "$pass" ]; then url_parse_array["pass"]=${pass} fi # ホスト名を抜く(ホスト+ポートを取り出して、そこからホスト名だけ取り出す) local hostname_port=${authority%%/*} url_parse_array["hostname"]=${hostname_port%%:*} # ポート番号を抜く local port=${hostname_port#*:} if [ ${url_parse_array["hostname"]} != "$port" ]; then url_parse_array["port"]="$port" fi } parse_url $1 echo ${url_parse_array["scheme"]} echo ${url_parse_array["uid"]} echo ${url_parse_array["pass"]} echo ${url_parse_array["hostname"]} echo ${url_parse_array["port"]} echo ${url_parse_array["hierpart"]} echo ${url_parse_array["query"]} echo ${url_parse_array["fragment"]}