Skip to content

Instantly share code, notes, and snippets.

@inkblot
Created March 29, 2020 02:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save inkblot/507c58c70cca4f9358185ec895a62b5c to your computer and use it in GitHub Desktop.
Save inkblot/507c58c70cca4f9358185ec895a62b5c to your computer and use it in GitHub Desktop.
Parse a URL in bash without forking
#!/bin/bash
_SELF="${0##*/}"
_HERE="$(dirname $(realpath ${0}))"
function parse_url() {
local url _url __url proto uphp user_pass host_port user pass host port path query_string
url="${1}"
proto="${url%://*}" # proto: everything up to the first '://'
# There should definitely be a proto, neither empty nor equal to url
if [ "${proto}" == "" -o "${proto}" == "$url" ]; then
echo "Invalid url: ${url}" >&2
return 1
fi
_url="${url:$((3 + ${#proto}))}" # _url: url minus "${proto}://"
uphp="${_url%%/*}" # uphp (User-Password-Host-Port): everything up to the first '/' in _url
__url="${_url:$((${#uphp} + 1))}" # __url: _url minus uphp
user_pass="${uphp%%@*}"
if [ "${user_pass}" == "${uphp}" ]; then
user_pass=""
host_port="${uphp}"
else
host_port="${uphp#*@}"
fi
user="${user_pass%%:*}" # user: everything up to the first ':' in user_pass
if [ "${user}" == "${user_pass}" ]; then
pass=""
else
pass="${user_pass#*:}" # pass: everything after the first ':' in user_pass, but only if there was a ':'
fi
host="${host_port%%:*}" # host: everything up to the first ':' in host_port
if [ "${host}" == "${host_port}" ]; then
port="80"
else
port="${host_port#*:}" # port: everything after the first ':' in host_port, but only if there was a ':'
fi
path="${__url%%\?*}" # path: everything up to the first '?' in __url
if [ "${path}" == "${__url}" ]; then
query_string=""
else
query_string="${__url%*\?}" # query_string: everything after the first '?' in __url, but only if there was a '?'
fi
echo "{"\
"\"proto\": \"${proto}\","\
"\"host\": \"${host}\","\
"\"port\": ${port},"\
"\"username\": \"${user}\","\
"\"password\": \"${pass}\","\
"\"path\": \"${path}\","\
"\"query_string\": \"${query_string}\""\
"}"
}
if [ "${_SELF}" = "parse-url.sh" ]; then
set -eu
parse_url "$@"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment