This is something that has always annoyed me about bash scripts… The fact that it’s difficult to run
/path/to/script.sh --foo=bar -v -n 10 blah -one='last arg'
So I decided to write up a bash function that let me easily (once the function was complete) access this type of information. And because I like sharing, here it is:
#!/bin/bash function getopt() { var="" wantarg=0 for (( i=1; i< =$#; i+=1 )); do lastvar=$var var=${!i} if [ "$var" = "" ]; then continue fi echo \ $var | grep -q -- '=' if [ $? -eq 0 ]; then ## -*param=value var=$(echo \ $var | sed -r s/'^[ ]*-*'/''/) myvar=${var%=*} myval=${var#*=} eval "${myvar}"="'$myval'" else echo \ $var | grep -E -q -- '^[ ]*-' if [ $? -eq 0 ]; then # -*param$ var=$(echo \ $var | sed -r s/'^[ ]*-*'/''/) eval "${var}"=1 wantarg=1 else echo \ $var | grep -E -- '^[ ]*-' if [ $? -eq 0 ]; then # the current one has a dash, so cannot be # the argument to the last parameter wantarg=0 fi if [ $wantarg -eq 1 ]; then # parameter argument val=$var var=$lastvar eval "${var}"="'${val}'" wantarg=0 else # parameter if [ "${!var}" = "" ]; then eval "${var}"=1 fi wantarg=0 fi fi fi done } OIFS=$IFS; IFS=$(echo -e " "); getopt $@; IFS=$OIFS
now at this point (assuming the above command line parameter and script) I should have access to the following variables: $foo ("bar") $v (1) $n (10) $blah (1) $one ("last arg"), like so:
OIFS=$IFS; IFS=$(echo -e " "); getopt $@; IFS=$OIFS echo -e " foo:\t$foo v:\t$v n:\t$n blah:\t$blah one:\t$one "
You might be curious about this line:
OIFS=$IFS; IFS=$(echo -e " "); getopt $@; IFS=$OIFS
IFS is the variable that tells bash how strings are separated (and mastering its use will go a long way towards enhancing your bash scripting skills.) Anyhow, by default IFS=” ” which normally is OK, but in our case we dont want “last arg” to be two seperate strings, but one. I cannot put the IFS assignment inside the function because by that point bash has already split the variable, it needs to be done at a level of the script in which $@ has not been touched yet. So I store the current IFS variable in $OIFS (Old IFS) and set IFS to a newline character. After running the function we reassign IFS to what it was beforehand. This is because I dont know what you might be doing with your IFS. There are lots of reasons you might have already assigned it to something else, and I wouldnt want to break your flow. So we do the polite thing.
And in case the above gets munged for some reason you can see the plain text version here: bash-getopt/getopt.sh
Anyways, hope this helps someone out. If not it’s still here for me when *I* need it 😉