问题
Is it possible to pass command line arguments to shell script as name value pairs, something like
myscript action=build module=core
and then in my script, get the variable like
$action
and process it?
I know that $1....and so on can be used to get variables, but then won't be name value like pairs. Even if they are, then the developer using the script will have to take care of declaring variables in the same order. I do not want that.
回答1:
In the Bourne shell, there is a seldom-used option '-k
' which automatically places any values specified as name=value
on the command line into the environment. Of course, the Bourne/Korn/POSIX shell family (including bash) also do that for name=value
items before the command name:
name1=value1 name2=value2 command name3=value3 -x name4=value4 abc
Under normal POSIX-shell behaviour, the command
is invoked with name1
and name2
in the environment, and with four arguments. Under the Bourne (and Korn and bash, but not POSIX) shell -k
option, it is invoked with name1
, name2
, name3
, and name4
in the environment and just two arguments. The bash
manual page (as in man bash
) doesn't mention the equivalent of -k
but it works like the Bourne and Korn shells do.
I don't think I've ever used it (the -k
option) seriously.
There is no way to tell from within the script (command
) that the environment variables were specified solely for this command; they are simply environment variables in the environment of that script.
This is the closest approach I know of to what you are asking for. I do not think anything equivalent exists for the C shell family. I don't know of any other argument parser that sets variables from name=value
pairs on the command line.
With some fairly major caveats (it is relatively easy to do for simple values, but hard to deal with values containing shell meta-characters), you can do:
case $1 in
(*=*) eval $1;;
esac
This is not the C shell family. The eval
effectively does the shell assignment.
arg=name1=value1
echo $name1
eval $arg
echo $name1
回答2:
This worked for me:
for ARGUMENT in "$@"
do
KEY=$(echo $ARGUMENT | cut -f1 -d=)
VALUE=$(echo $ARGUMENT | cut -f2 -d=)
case "$KEY" in
STEPS) STEPS=${VALUE} ;;
REPOSITORY_NAME) REPOSITORY_NAME=${VALUE} ;;
*)
esac
done
echo "STEPS = $STEPS"
echo "REPOSITORY_NAME = $REPOSITORY_NAME"
Usage
bash my_scripts.sh STEPS="ABC" REPOSITORY_NAME="stackexchange"
Console result :
STEPS = ABC
REPOSITORY_NAME = stackexchange
STEPS and REPOSITORY_NAME are ready to use in the script.
It does not matter what order the arguments are in.
HTH
回答3:
env action=build module=core myscript
You said you're using tcsh. For Bourne-based shells, you can drop the "env", though it's harmless to leave it there. Note that this applies to the shell from which you run the command, not to the shell used to implement myscript
.
If you specifically want the name=value pairs to follow the command name, you'll need to do some work inside myscript
.
回答4:
Extending on Jonathan's answer, this worked nicely for me:
#!/bin/bash
if [ "$#" -eq "0" ]; then
echo "Error! Usage: Remind me how this works again ..."
exit 1
fi
while [[ "$#" > "0" ]]
do
case $1 in
(*=*) eval $1;;
esac
shift
done
来源:https://stackoverflow.com/questions/5499472/specify-command-line-arguments-like-name-value-pairs-for-shell-script