Just annotations of little "how to's", so I know I can find how to do something I've already done when I need to do it again, in case I don't remember anymore, which is not unlikely. Hopefully they can be useful to others, but I can't guarantee that it will work, or that it won't even make things worse.
Parsing script arguments in bash, without getopt(s)
Posted 03-12-2016 at 05:15 PM by the dsc
Nifty. Just found that on stackoverflow:
http://stackoverflow.com/questions/1...uments-in-bash
I've just tested the second method so far, as I've found somewhat weird that the first one is somehow extracting the parameters from "$2" all the time, but I suppose "shift" literally shifts the current $N to $N+1 or something like that.
http://stackoverflow.com/questions/1...uments-in-bash
Quote:
Originally Posted by Bruno Bronosky, cwd, et al.
Preferred Method: Using straight bash without getopt[s]
I originally answered the question as the OP asked. This Q/A is getting a lot of attention, so I should also offer the non-magic way to do this. I'm going to expand upon guneysus's answer to fix the nasty sed and include Tobias Kienzler's suggestion.
Two of the most common ways to pass key value pair arguments are:
Straight Bash Space Separated
Usage ./myscript.sh -e conf -s /etc -l /usr/lib /etc/hosts
Straight Bash Equals Separated
To better understand ${i#*=} search for "Substring Removal" in this guide. It is functionally equivalent to `sed 's/[^=]*=//' <<< "$i"` which calls a needless subprocess or `echo "$i" | sed 's/[^=]*=//'` which calls two needless subprocesses.
[...]
I originally answered the question as the OP asked. This Q/A is getting a lot of attention, so I should also offer the non-magic way to do this. I'm going to expand upon guneysus's answer to fix the nasty sed and include Tobias Kienzler's suggestion.
Two of the most common ways to pass key value pair arguments are:
Straight Bash Space Separated
Usage ./myscript.sh -e conf -s /etc -l /usr/lib /etc/hosts
Code:
# note: if this is set to > 0 the /etc/hosts part is not recognized ( may be a bug ) while [[ $# > 1 ]] do key="$1" case $key in -e|--extension) EXTENSION="$2" shift # past argument ;; -s|--searchpath) SEARCHPATH="$2" shift # past argument ;; -l|--lib) LIBPATH="$2" shift # past argument ;; --default) DEFAULT=YES ;; *) # unknown option ;; esac shift # past argument or value done echo FILE EXTENSION = "${EXTENSION}" echo SEARCH PATH = "${SEARCHPATH}" echo LIBRARY PATH = "${LIBPATH}" echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l) if [[ -n $1 ]]; then echo "Last line of file specified as non-opt/last argument:" tail -1 $1 fi
Code:
#!/bin/bash for i in "$@" do case $i in -e=*|--extension=*) EXTENSION="${i#*=}" shift # past argument=value ;; -s=*|--searchpath=*) SEARCHPATH="${i#*=}" shift # past argument=value ;; -l=*|--lib=*) LIBPATH="${i#*=}" shift # past argument=value ;; --default) DEFAULT=YES shift # past argument with no value ;; *) # unknown option ;; esac done echo "FILE EXTENSION = ${EXTENSION}" echo "SEARCH PATH = ${SEARCHPATH}" echo "LIBRARY PATH = ${LIBPATH}" echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l) if [[ -n $1 ]]; then echo "Last line of file specified as non-opt/last argument:" tail -1 $1 fi
[...]
Total Comments 2
Comments
-
Using '=' to separate a short-option from its argument, or using a space to separate a long-option from its argument are non-standard and best avoided. I wouldn't recommend either of the above solutions in their current form.
Posted 03-14-2016 at 08:08 AM by GazL -
While I agree with the above, I use something similar to #1 if for some reason I want to avoid getopts. Instead of testing the number of arguments remaining, I test the value of $1.
I don't understand why the author of the second "solution" chose to shift within every condition. using shift at the end of the loop like the first to me would be less error prone (what if you add an argument, and forget to add shift?).Posted 03-20-2016 at 01:00 PM by goumba