1

To add options, I have the following in one of my scripts:

parse_opts() {
    while [ $# -gt 0 ]; do
    case "$1" in
        -h|--help)
        help=1
        shift
        ;;
        -r|--raw)
        raw=1
        shift
        ;;
        -c|--copy)
        copy=1
        shift
        ;;
        -s|--sensitive)
        sensitive=1
        shift
        ;;
        -i|--insensitive)
        insensitive=1
        shift
        ;;
        *)
        shift
        ;;
    esac
    done
}

There is only one problem, I cannot use multiple options at the same time. For example, using -r -s works but using -rs does not. How can I programmatically make it work without adding separate entries? The shell I am using is sh.

Edit: I figured out how to do it. It is based on this stackoverflow answer. I copied and pasted it but replaced it with what I need.


New code:

while getopts hcsi-: OPT; do
    # Support long options: https://stackoverflow.com/a/28466267/519360
    if [ "$OPT" = "-" ]; then
        OPT="${OPTARG%%=*}"
        OPTARG="${OPTARG#$OPT}"
        OPTARG="${OPTARG#=}"
    fi
    case "$OPT" in
        h|help) help; exit 0 ;; # Call the `help´ function and exit.
        c|copy) copy=1 ;;
        s|sensitive) case_sensitivity="sensitive" ;;
        i|insensitive) case_sensitivity="insensitive" ;;
        ??*) printf '%s\n' "Illegal option --$OPT" >&2; exit 2 ;;
        ?) exit 2 ;; # Error reported via `getopts´
    esac
done

shift $((OPTIND-1)) # Remove option arguments from the argument list
Amarakon
  • 289
  • 3
  • 9
  • which shell is this, specifically? Because zsh does bring a much more powerful option parser. (I'll be honest, I still think "easy to use" is still different, but at least it's possible to implement this if you follow a fixed recipe) – Marcus Müller Jul 05 '22 at 07:22
  • 2
    Have you heard of `getopts`? – FelixJN Jul 05 '22 at 08:39
  • 4
    @FelixJN, only the `getopts` from ksh93 does long options though (and not even the same was as GNU `getopt_long()` does). `util-linux` `getopt` can do it though. – Stéphane Chazelas Jul 05 '22 at 10:06
  • The shell I am using is simply sh (dash). – Amarakon Jul 05 '22 at 20:36
  • @FelixJN I have not heard of `getopts`, how can I use it? – Amarakon Jul 05 '22 at 20:37
  • https://dashdash.io/1/getopt gives an overview of `getopt`, as recommended by Stéphane. The `getopts` command is a more powerful builtin which directly modifies shell variables, but you'd have to switch to bash or ksh93. – Henk Langeveld Jul 05 '22 at 21:08
  • @HenkLangeveld, `getopts` (with the s) is supported in Dash too, and it's a standard (builtin) utility. But it doesn't do long options in most shells. `getopt` (without the s) isn't standard, and though you get combined short options as well as long options with the _util-linux one_ (which indeed you linked to), you need to be careful to not get the "tradional" ones which can't deal with whitespace in the arguments (and maybe other things) – ilkkachu Jul 05 '22 at 21:58
  • @ilkkachu The options here are all booleans, so `getopts` could be used with an additional `-` option taking an argument. All arguments could be handled as normal with `getopts` and the `-` option and its option-argument could be handled by an inner `case` statement. Just thinking aloud... – Kusalananda Jul 05 '22 at 22:38
  • @Kusalananda, hmm, it looks like that might even work? If it treated `-` the same as letters, it'd eat `-- foo` (with the space) as the option and option-argument, but it seems to be smarter than that. – ilkkachu Jul 05 '22 at 22:49
  • I figured out how to do it. It is based on this stackoverflow answer: https://stackoverflow.com/a/28466267. I copied and pasted it but replaced it with what I need. – Amarakon Jul 05 '22 at 23:05
  • if you're not going to indent your case statements properly, at least put an empty line between each case to make it somewhat readable. – cas Jul 06 '22 at 07:23
  • 1
    @Amarakon If you have a solution for your specific use case, then consider posting a proper answer. – Kusalananda Jul 06 '22 at 07:48
  • @Kusalananda like I said, I just copy and pasted from a Stack Overflow answer and changed the options. It's better explained there. – Amarakon Jul 06 '22 at 17:16
  • 1
    You linked [my answer on Stack Overflow](https://stackoverflow.com/a/28466267/519360) and used it to refine your answer, but I think you missed that its use of `getopts` makes it vastly more capable than your own implementation. For example, your code doesn't support combining options, like `-rc`, nor does your code complain given invalid options, nor does it support arguments to options. Follow that link for a better solution implementing long and short options with optional arguments and proper errors. – Adam Katz Mar 08 '23 at 19:54
  • @AdamKatz I did not add the new code block in my post, that was an edit made by someone else. I will update my post with the new code. Sorry for the confusion. – Amarakon Mar 09 '23 at 18:01
  • Possible duplicate of [getopt, getopts or manual parsing - what to use when I want to support both short and long options?](https://unix.stackexchange.com/q/62950) – Stéphane Chazelas Mar 09 '23 at 18:49

0 Answers0