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.