home of the madduck/ blog/
Parsing arguments in a shell script

Since shell is a rather unpredictable programming language, which seems not to allow manipulation of variables in parent processes, parsing arguments has always been a bit cumbersome. For instance, check out lines 74 through 123 of /usr/bin/deb-reversion (package devscripts) for the way I used to do things, which involves a sort of state machine to handle options taking arguments.

Just last night, I came up with another means, and while it felt like an incredible hack at the time, I am starting to like it. This method can be combined with getopt, I just use it to parse guessnet test lines in /etc/network/interfaces right now:

eval $(while [ -n "${1:-}" ]; do
    case "$1" in
      mac) echo MACADDR="'$2'"; shift;;
      essid) echo ESSID="'$2'"; shift;;
      ie) echo IE="'$2'"; shift;;
      *)
        echo "$ME: E: invalid argument: $1" >&2
        exit 1;;
    esac
    shift
  done || exit $?) || exit $?

When this is done, any (or none) of the three variables MACADDR, ESSID, and IE are defined in the shell script's environment. If an argument is required, I can do checks following the loop, or use getopt to parse $@ before looping over its components. Of course, the last line really does make it look like a hack, but it works and it's flexible...

If I now look at /usr/share/guessnet/test/test-wireless, I wonder how Thomas Hood managed to get things working, specifically because he sets variables inside a while loop, and then uses them outside of the loop --exactly the sort of construct that drove me nuts previously. Maybe it has to do with my religious use of set -u, maybe not. In any case, I am simply not willing to investigate.