4 ms·
To have variable typos result in errors with `set -u`, then expand an array that is defined but may be empty, I need write it as `${ARRAY[@]+"${ARRAY[@]}"`. (F
by MereInterest 5y ago
To have variable typos result in errors with `set -u`, then expand an array that is defined but may be empty, I need write it as `${ARRAY[@]+"${ARRAY[@]}"`. (Further explanation: https://stackoverflow.com/questions/7577052/bash-empty-array-expansion-with-set-u https://stackoverflow.com/questions/7577052/bash-empty-array...) But maybe bash arrays are too new a feature, and should be avoided, so let's look at something simpler, like command-line arguments.
Parsing command-line arguments is easy, but parsing them correctly is ridiculously hard. `getopts` doesn't handle long flags, so it's out. `getopt` doesn't handle arguments with spaces in them, unless you have a version with non-standard extensions, so it's out. You're left with manual parsing, and it's a royal pain to make sure you handle every expected case (short/long flags, clusters of short flags, trailing arguments to be passed through to a subprocess, short/long options whose value is in the next argument, long options whose value is after an equals sign, and several others I'm probably forgetting about). And this is just to get the arguments into your script, before you actually do anything with it.
I agree that bash has effective idioms, and learning those idioms can make scripts easier to write. I strongly disagree that bash is "as maintainable as anything else", and scripts beyond a few hundred lines should be rewritten before they can continue growing.
- drran 5y agoYou can use bash-modules arguments library to generate argument parser for you.
- MereInterest 5y agoThank you, I haven't heard of that one before. However, all the examples look like it gets called as an external library, which would either need to be distributed with a script, or to already be installed by a user. Is there a feature I'm not seeing that would generate an argument parser without external dependencies?
- drran 5y agoYes, arguments::generate_parser function. Install bash-modules, then run `. import.sh log arguments`, then call `arguments::generate_parser '--foo)FOO;String'` , and it will generate function with parser, which include parser for foo option for both `--foo VALUE` and `--foo=VALUE`: ... --foo) FOO="${2:?ERROR: String value is required for \"-f|--foo\" option. See --help for details.}" shift 2 ;; --foo=*) FOO="${1#*=}" shift 1 ;; ...
- databasher 5y agoBash `getopts` handles short and long arguments gnu-style without any problem. The following code handles args like "-h", "-i $input-file", "-i$input-file", "--in=$input-file", and "--help": while getopts :i:h-: option do case $option in # accept -i $input-file, -i$input-file i ) input_file=$OPTARG;; h ) print_help;; - ) case $OPTARG in help ) print_help;; help=* ) echo "Option has unexpected argument: ${OPTARG%%=*}" >&2; exit 1;; in=* ) input_file=${OPTARG##*=};; in ) echo "Option missing argument: $OPTARG" >&2; exit 1;; * ) echo "Bad option $OPTARG" >&2; exit 1;; esac;; '?' ) echo "Unknown option $OPTARG" >&2; exit 1;; : ) echo "Option missing argument: $OPTARG" >&2; exit 1;; * ) echo "Bad state in getopts" >&2; exit 1;; esac done shift $((OPTIND-1))