1

I have created a script for /bin/sh posix shell that handles flags using the getopts utility, now I realized that it's probably not the best choice in my case, it's an external dependency and in the end it's not even that flexible, it's probably good for flags that are 1 char long, but I would like to use more "verbose" and intuitive flags like --config or --value-for-a=42 .

Assuming that I would like to implement something that is self contained, what is the alternative ?

user2485710
  • 9,451
  • 13
  • 58
  • 102
  • `getopts` is a shell built-in, not an external dependency. – Jonathan Leffler Mar 14 '14 at 03:52
  • possible duplicate of [Using getopts in bash shell script to get long and short command line options](http://stackoverflow.com/questions/402377/using-getopts-in-bash-shell-script-to-get-long-and-short-command-line-options) – Jonathan Leffler Mar 14 '14 at 03:53
  • @JonathanLeffler in the `sh` shell ? are you sure ? anyway I have to use longer flags – user2485710 Mar 14 '14 at 03:53
  • Rolling your own system will be hard work to do well, and generally is not a good idea. If you must do it, model it on the GNU extended `getopt` program (which in turn is based on the GNU `getopt()` and `getopt_long()` functions). – Jonathan Leffler Mar 14 '14 at 03:54
  • @JonathanLeffler can you expand on that with a complete post ? What do you mean with "it's not a good idea" and how to handle longer flags with `getopts` ? – user2485710 Mar 14 '14 at 03:56
  • 1
    It depends which `sh` you're referring to; you need to identify your platform and your shell more precisely. All the POSIX-ish shells I know of have `getopts` built in — Bash, Korn Shell, Z Shell. Archaic Bourne shell might not; System V Bourne shell did. As to expanding my comments into an answer — no, the proposed duplicate already covers the subject in extenso. – Jonathan Leffler Mar 14 '14 at 03:56

1 Answers1

1

This is one quick and dirty method:

AAA=default
# example: BBB left unspecified so you can optionally override from environment
XYZ=${XYZ:-0}   # optional so you could override from environment
ABC=${ABC:-0}
while test $# -gt 0 ; do

  # switches
  if test "$1" = "--flag-xyz" ; then XYZ=1 ; shift ; continue; fi
  if test "$1" = "--flag-abc" ; then ABC=1 ; shift ; continue; fi

  # options with arguments
  case "$1" in
  --option-aaa=*) AAA="${1##--option-aaa=}" ; shift; continue; break ;;
  --option-bbb=*) BBB="${1##--option-bbb=}" ; shift; continue; break ;;
  esac

  # unknown - up to you - positional argument or error?
  echo "Unknown option $1"
  shift
done

Customise as required.

The advantage of this method is it is order independent, you can tweak options for edge cases in your syntax if needed. And it is simple otherwise.

If you need to enforce ordering break the processing into multiple statements with a break from the relevant while statement when needed.

Downside is there is a bit of the duplication that getopt sometimes avoids.

EDIT: change [==] and -gt to test

6EQUJ5
  • 3,142
  • 1
  • 21
  • 29
  • this script mainly works for the `bash` it's not really for the `sh`. – user2485710 Mar 14 '14 at 03:54
  • I thought I just tested it on sh (digs around) Sneaky, the Linux I have in front of me symlinks /usr/bin/sh --> /bin/bash Couldn't you use the same approach though, just the syntax would be a bit different? – 6EQUJ5 Mar 14 '14 at 04:17
  • Looking at http://www.freebsd.org/cgi/man.cgi?sh sh supports case, shift, esac, break, continue $# and ${##} - so presumably just '==' thats missing? edit happening... – 6EQUJ5 Mar 14 '14 at 04:21
  • I think that the evaluation with `:` it's likely to break in a `sh` compliant shell, for example `{ABC:-0}` it's likely to be not compatible with `sh`. – user2485710 Mar 14 '14 at 04:25
  • You could be right. That bit was just gold plating though ;-) – 6EQUJ5 Mar 14 '14 at 04:27
  • 1
    FWIW `${ABC:-0}` is POSIX compliant. – Scrutinizer Mar 18 '14 at 21:45