Skip to content

Instantly share code, notes, and snippets.

@akutz
Last active October 31, 2018 21:54
Show Gist options
  • Save akutz/7a39159bbbe9c299c79f1d2107ef1357 to your computer and use it in GitHub Desktop.
Save akutz/7a39159bbbe9c299c79f1d2107ef1357 to your computer and use it in GitHub Desktop.
A POSIX-compliant means of manipulating a shell's arguments

The script posix-args.sh provides two POSIX-compliant functions for getting the last argument in an array as well as getting all but the last argument. The following example illustrates how to use the functions and the expected results:

t="$(mktemp)" && \
curl -o "${t}" -sSL \
http://bit.ly/posix-args && \
. "${t}" && rm -f "${t}"         # load the two functions from "posix-args.sh"

set -- one two three four        # set the shell's arguments value
echo "there are ${#} args"       # prints "there are 4 args"

args="$(only_last_arg "${@}")"   # get the last argument
eval "set -- ${args}"            # update the shell's arguments with the new value
echo "there are ${#} args"       # prints "there are 1 args"
for arg; do echo "${arg}"; done  # prints "four"

set -- one two three four        # reset the shell's arguments value
echo "there are ${#} args"       # prints "there are 4 arguments"

args="$(trim_last_arg "${@}")"   # get all the args except the last arg
eval "set -- ${args}"            # update the shell's arguments with the new value
echo "there are ${#} args"       # prints "there are 3 args"
for arg; do echo "${arg}"; done  # prints "one", "two", "three"
#!/bin/sh
# posix compliant
# verified by https://www.shellcheck.net
# Returns the last argument as an array using a POSIX-compliant method
# for handling arrays.
only_last_arg() {
_l="${#}" _i=0 _j="$((_l-1))" && while [ "${_i}" -lt "${_l}" ]; do
if [ "${_i}" -eq "${_j}" ]; then
printf '%s\n' "${1}" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
fi
shift; _i="$((_i+1))"
done
echo " "
}
export only_last_arg
# Returns all but the last argument as an array using a POSIX-compliant method
# for handling arrays.
trim_last_arg() {
_l="${#}" _i=0 _j="$((_l-1))" && while [ "${_i}" -lt "${_l}" ]; do
if [ "${_i}" -lt "${_j}" ]; then
printf '%s\n' "${1}" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/"
fi
shift; _i="$((_i+1))"
done
echo " "
}
export trim_last_arg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment