How to create a userfriendly bash script (command line parsing)
Well, I had to do some very basic calculations based on simple csv files. I had to pick the second field and calculate the overall mean in a file of that field. There are some very good awk tutorials out there, but I was very disappointed about how little they talk about how to surround the awk command with a little bash sugar to produce a small reusable tool. So I just wanted to quickly point out how to something like that WELL. The basic awk algorithm is very simple, but you really should surround that simple awk command with some basic tests. It is pretty important, at least as far as I am concerned, that tools are always blessed with a nice command line parser, that it allows for direct file referencing and piping as well, if an error occurs please make it write to stderr and make it returns correct exit status codes. It's just good practice. Granted, bash command line parsing is not too much fun, but there are a couple of tricks, but the exit codes are so easy to deal with, just remember putting in one line.
I'll just throw out the code, so look at it and maybe you can identify all the things that went into the surrounding sugar:
- #!/bin/bash
- do_usage(){
- echo>&2 "Usage: `basename $0` [-|-f file|--file file] [--] [file ...]"
- exit 1
- }
- test_if_last_argument() {
- if [ $# -gt 0 ]; then
- do_usage
- fi
- }
- filename=
- while [ $# -gt 0 ]
- do
- case "$1" in
- -f|--file) filename="$2"; shift;;
- --) shift; break;;
- -) filename="-"; shift; test_if_last_argument "$@"; break;;
- -*) do_usage;;
- *) break;; # terminate while loop
- esac
- shift
- done
- awk '
- BEGIN {
- FS=","
- }
- {
- mean = mean + $2
- count++
- }
- END {
- mean = mean / count
- print mean
- }
- ' "$filename" "$@"
- exit $?
It is an excellent example of how there usually 56.7% of the lines are just there for maintenance and only 43.3% actually do something useful. But always remember: 42.7 percent of all statistics are made up on the spot.
I'll explain why I put those maintenance lines in, why it's "$@" and not $@, etc ... tomorrow.
