$@ becoming messed up
I am trying to write a bash script that will examine the first argument, and if its one of particular values then it will remove that argument from the arguments and set some stuff up:
#!/bin/bash -x
echo args=$@
if [ "$1" == "valgrind" ]; then
echo running under valgrind
set $tool=valgrind
shift 1
elif [ "$1" == "debug" ]; then
echo running under gdb
set $tool=gdb --args
shift 1
else
echo running normally
set $tool=""
fi
echo tool=$tool
echo args=$@
However, When I run this it consumes all the arguments! E.g.:
./my_script valgrind --something=y -开发者_JAVA技巧r
+ echo args=valgrind --something=y -r
args=valgrind --something=y -r
+ '[' valgrind == valgrind ']'
+ echo running under valgrind
running under valgrind
+ set =valgrind
+ shift 1
+ echo tool=
tool=
+ echo args=
args=
and if the if-statements aren't followed:
./my_script valgrindx --something=y -r
+ echo args=valgrindx --something=y -r
args=valgrindx --something=y -r
+ '[' valgrindx == valgrind ']'
+ '[' valgrindx == debug ']'
+ echo running normally
running normally
+ set =
+ echo tool=
tool=
+ echo args==
args==
What is happening, and how to fix it?
It's because set blah blah blah
actually sets the $1 ... $N
parameters to whatever the arguments evaluate to, as shown in the following transcript:
pax$ echo $1
pax$ set $tool=hello ; echo $1
=hello
pax$ tool=xyzzy ; set $tool=hello ; echo $1
xyzzy=hello
(in that second command, $tool
is not set which is why it comes out as blank).
In your case, set $tool=valgrind
is setting $1
to whatever the string $tool=valgrind
evaluates to, which is why $@
is changing. It is not setting the environment variable tool
to valgrind
.
If you want to set the variable, just use:
tool=valgrind
or, to make it available to subshells:
export tool=valgrind
The set
command is used to either display environment stuff or set shell attributes and arguments, not named variables. If you have a look at the man bash_builtins
manpage, you'll see the bit that explains this behaviour (search for the description of set
):
Any arguments remaining after the options are processed are treated as values for the positional parameters and are assigned, in order, to
$1, $2, ... $n
.
set $tool=valgrind
should be
tool=valgrind
The set command is for something else in bash, try 'help set'.
set $tool=valgrind
should be just tool=valgrind
. set
has a different in Bash/Bourne-compatible shells than it has in the C shell.
You should check the getopts
too, for the -x argument
handling. See here
精彩评论