$myscript.sh -host blah -user blah -pass blah
I want to pass arguments into it.
I'm used to doing $1, $2, $3....but I want to start naming them
There are lots of ways to parse arguments in sh. Getopt is good. Here's a simple script that parses things by hand:
#!/bin/sh
# WARNING: see discussion and caveats below
# this is extremely fragile and insecure
while echo $1 | grep -q ^-; do
# Evaluating a user entered string!
# Red flags!!! Don't do this
eval $( echo $1 | sed 's/^-//' )=$2
shift
shift
done
echo host = $host
echo user = $user
echo pass = $pass
echo args = $@
A sample run looks like:
$ ./a.sh -host foo -user me -pass secret some args
host = foo
user = me
pass = secret
args = some args
Note that this is not even remotely robust and massively open to security holes since the script eval's a string constructed by the user. It is merely meant to serve as an example for one possible way to do things. A simpler method is to require the user to pass the data in the environment. In a bourne shell (ie, anything that is not in the csh family):
$ host=blah user=blah pass=blah myscript.sh
works nicely, and the variables $host, $user, $pass will be available in the script.
#!/bin/sh
echo host = ${host:?host empty or unset}
echo user = ${user?user not set}
...
declare instead of eval would be more secure.| tr -d '\012', as it is not necessary - command substitution automatically trims all trailing newlines.declare without using sed (or eval): declare "${1#-}"=$2 . Note that neither this nor the technique in this answer will handle two or more leading hyphens nor embedded hyphens. Also, hyphens aren't allowed in Bash variable names. A separate step could be added to convert hyphens to underscores which are allowed: var=${1#-}; declare "${var//-/_}"="$2"Here is a simple way to handle both long and short options:
while [[ $1 == -* ]]; do
case "$1" in
-h|--help|-\?) show_help; exit 0;;
-v|--verbose) verbose=1; shift;;
-f) if [[ $# > 1 && $2 != -* ]]; then
output_file=$2; shift 2
else
echo "-f requires an argument" 1>&2
exit 1
fi ;;
--) shift; break;;
-*) echo "invalid option: $1" 1>&2; show_help; exit 1;;
esac
done
From How can I handle command-line arguments (options) to my script easily?
-vf to represent -v -f./bin/sh (without Bash).getopts is a Bash builtin while getopt is an external utility. The former only works with short options (e.g. -e) while the latter will also work with long ones (e.g. -foo). Note that there are some issues with the latter that have to be addressed (later versions of getopt have fewer issues).I adopt above William Pursell example (with Dennis Williamson advice) for parameters in this format: script -param1=value1 -param2=value2 ...
Here is code with one-line arguments parser (save it in file 'script'):
#!/bin/bash
while echo $1 | grep ^- > /dev/null; do declare $( echo $1 | sed 's/-//g' | sed 's/=.*//g' | tr -d '\012')=$( echo $1 | sed 's/.*=//g' | tr -d '\012'); shift; done
echo host = $host
echo user = $user
echo pass = $pass
You call it like that:
script -host=aaa -user=bbb -pass=ccc
and result is
host = aaa
user = bbb
pass = ccc
Do someone know shorter code to parse arguments than this above?
switch,getopts(POSIX shell builtin), andgetopt(not recommended unless it's the util-linux version and you use its non-POSIX features to avoid problems with empty args, and so on.)