Last active
August 29, 2015 14:12
-
-
Save dnschneid/a6d3b9628c2f2baab540 to your computer and use it in GitHub Desktop.
getopts positional parameter reordering hack
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh -e | |
set -e | |
# Works mostly like built-in getopts but silently coalesces positional arguments. | |
# Does not take parameters. Set getopts_string prior to calling. | |
# Sets getopts_var and getopts_arg. | |
# $@ will be left with the positional arguments, so you should NOT shift at all. | |
# In bash, enables alias expansion until arguments are done being processed. | |
shopt -q -s expand_aliases 2>/dev/null || true | |
getopts_npos=0 | |
getopts_dashdash='' | |
alias getopts_nextarg='getopts_ret=1 | |
while [ "$#" -gt "$getopts_npos" ]; do | |
if [ -z "$getopts_dashdash" ] && getopts "$getopts_string" getopts_var; then | |
if [ "$(($#+1-OPTIND))" -lt "$getopts_npos" ]; then | |
# Bad parameter usage ate a positional argument. | |
# Generate the proper error message by abusing getopts. | |
set -- "-$getopts_var" | |
getopts "$getopts_var:" getopts_var | |
shift | |
fi | |
getopts_arg="$OPTARG" | |
getopts_ret=0 | |
# Avoid -- confusion by shifting if OPTARG is set | |
if [ -n "$OPTARG" ]; then | |
shift "$((OPTIND-1))" | |
OPTIND=1 | |
fi | |
break | |
fi | |
# Do not let getopts consume a -- | |
if [ "$OPTIND" -gt 1 ]; then | |
shift "$((OPTIND-2))" | |
if [ "$1" != "--" ]; then | |
shift | |
fi | |
fi | |
OPTIND=1 | |
if [ -z "$getopts_dashdash" -a "$1" = "--" ]; then | |
# Still need to loop through to fix the ordering | |
getopts_dashdash=y | |
else | |
set -- "$@" "$1" | |
getopts_npos="$((getopts_npos+1))" | |
fi | |
shift | |
done | |
if [ "$getopts_ret" = 1 ]; then | |
shopt -q -u expand_aliases 2>/dev/null || true | |
fi | |
[ "$getopts_ret" = 0 ]' | |
# Test application. | |
# Try running this script using some of these parameters, positionals, and --'s | |
# Try using -- after a parameter that takes -- as an argument | |
# Try adding a trailing parameter | |
# Try combining parameters together into one multi-switch | |
getopts_string='a:bdef:k:m:M:n:p:P:r:s:t:T:uUV' | |
while getopts_nextarg; do | |
echo "-$getopts_var $getopts_arg" | |
done | |
echo "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment