Split string on colon in /bin/sh
Just do:
case $1 in
(*:*) host=${1%:*} port=${1##*:};;
(*) host=$1 port=$default_port;;
esac
You may want to change the case $1
to case ${1##*[]]}
to account for values of $1
like [::1]
(an IPv6 address without port part).
To split, you can use the split+glob operator (leave a parameter expansion unquoted) as that's what it's for after all:
set -o noglob # disable glob part
IFS=: # split on colon
set -- $1 # split+glob
host=$1 port=${2:-$default_port}
(though that won't allow hostnames that contain a colon (like for that IPv6 address above)).
That split+glob operator gets in the way and causes so much harm the rest of the time that it would seem only fair that it be used whenever it's needed (though, I'll agree it's very cumbersome to use especially considering that POSIX sh
has no support for local scope, neither for variables ($IFS
here) nor for options (noglob
here) (though ash
and derivatives like dash
are some of the ones that do (together with AT&T implementations of ksh
, zsh
and bash
4.4 and above)).
Note that IFS=: read A B <<< "$1"
has a few issues of its own:
- you forgot the
-r
which means backslash will undergo some special processing. - it would split
[::1]:443
into[
and:1]:443
instead of[
and the empty string (for which you'd needIFS=: read -r A B rest_ignored
or[::1]
and443
(for which you can't use that approach) - it strips everything past the first occurrence of a newline character, so it can't be used with arbitrary strings (unless you use
-d ''
inzsh
orbash
and the data doesn't contain NUL characters, but then note that herestrings (or heredocs) do add an extra newline character!) - in
zsh
(where the syntax comes from) andbash
, here strings are implemented using temporary files, so it's generally less efficient than using${x#y}
or split+glob operators.
Just remove the :
in a separate statement; also, remove $host from the input to get the port:
host=${1%:*}
port=${1#"$host"}
port=${port#:}
Another thought:
host=${1%:*}
port=${1##*:}
[ "$port" = "$1" ] && port=''