Skip to content

Instantly share code, notes, and snippets.

@Decstasy
Last active January 16, 2024 18:42
Show Gist options
  • Save Decstasy/19814b80a3551b34d78e8be7f3b5e8d8 to your computer and use it in GitHub Desktop.
Save Decstasy/19814b80a3551b34d78e8be7f3b5e8d8 to your computer and use it in GitHub Desktop.
Parse Bash arguments without getopts or getopt
#!/bin/bash
# Dennis Ullrich
# Version 0.1-0 (2017-06-29)
# [email protected]
# Bash Version 3 required (it also works with ksh)
[[ ${BASH_VERSINFO[0]} -lt 3 ]] && exit 1
# Defaults
stdin=0
csv=0
param=""
# Put all arguments in a new array (because BASH_ARGV is read only)
ARGS=( "$@" )
for i in "${!ARGS[@]}"; do
case "${ARGS[i]}" in
'') # Skip if element is empty (happens when it's unsetted before)
continue
;;
-s|--stdin) stdin=1
;;
--csv) csv=1
;;
-p|--param) # Use +1 to access next array element and unset it
param="${ARGS[i+1]}"
unset 'ARGS[i+1]'
;;
--) # End of arguments
unset 'ARGS[i]'
break
;;
*) # Skip unset if our argument has not been matched
continue
;;
esac
unset 'ARGS[i]'
done
# In case you want to process more, there is nothing lost except the already parsed arguments with options.
# Keep in mind there was not a single shift!
echo "Unused Arguments:"
for i in "${!ARGS[@]}"; do
echo "$i: ${ARGS[i]}"
done
@sopos
Copy link

sopos commented Aug 25, 2017

Also your implementation does not allow short version of short options -abc as -a -b -c
This pre-processing should help

  local ARGS=()
  for i in "$@"; do
    if [[ "${i:0:1}" == "-" && "${i:1:1}" != "-" ]]; then
      for (( j=1; j<${#i}; j++ )); do
        ARGS+=("-${i:$j:1}")
      done
    else
      ARGS+=("$i")
    fi
  done

It is not almighty, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment