问题
Inside a bash script function, I need to work with the command-line arguments of the script, and also with another list of arguments. So I'm trying to pass two argument lists to a function, the problem is that multi-word arguments get split.
function params()
{
for PARAM in $1; do
echo "$PARAM"
done
echo .
for ITEM in $2; do
echo "$ITEM"
done
}
PARAMS="$@"
ITEMS="x y 'z t'"
params "$PARAMS" "$ITEMS"
calling the script gives me
myscript.sh a b 'c d'
a
b
c
d
.
x
y
'z
t'
Since there are two lists they must be passed as a whole to the function, the question is, how to iterate the elements while respecting multi-word items enclosed in single quotes 'c d' and 'z t'?
The workaround that I have (see below) makes use of BASH_ARGV so I need to pass just a single list to the function. However I would like to get a better understanding of what's going on and what's needed to make the above work.
function params()
{
for PARAM in "${BASH_ARGV[@]}"; do
echo "$PARAM"
done
echo .
for ITEM in "$@"; do
echo "$ITEM"
done
}
params x y 'z t'
calling the script gives me
myscript.sh a b 'c d'
c d
b
a
.
x
y
z t
... Which is how I need it (except that first list is reversed, but that would be tolerable I guess)
回答1:
function params()
{
arg=("$@")
for ((i=1;i<=$1;i++)) ;do
echo "${arg[i]}"
done
echo .
for ((;i<=$#-$1+2;i++)) ;do
echo "${arg[i]}"
done
}
items=(w x 'z t')
params $# "$@" "${items[@]}"
Assuming you call your script with args a b 'c d'
, the output is:
a
b
c d
.
x
y
z t
回答2:
Peter.O's answer above works fine, and this is an addendum to it, with an example.
I needed a function or script that would take multi-word arguments, that would then be used to search the list of running processes and kill those that matched one of the arguments. The following script does that. The function kill_processes_that_match_arguments
only needs one for
loop, because my need was only to iterate over the set of all arguments to the function. Tested to work.
#!/bin/bash
function kill_processes_that_match_arguments()
{
arg=("$@")
unset PIDS_TO_BE_KILLED
for ((i=0;i<$#;i++))
do
unset MORE_PIDS_TO_KILL
MORE_PIDS_TO_KILL=$( ps gaux | grep "${arg[i]}" | grep -v 'grep' | awk '{ print $2 }' )
if [[ $MORE_PIDS_TO_KILL ]]; then
PIDS_TO_BE_KILLED="$MORE_PIDS_TO_KILL $PIDS_TO_BE_KILLED"
fi
done
if [[ $PIDS_TO_BE_KILLED ]]; then
kill -SIGKILL $PIDS_TO_BE_KILLED
echo 'Killed processes:' $PIDS_TO_BE_KILLED
else
echo 'No processes were killed.'
fi
}
KILL_THESE_PROCESSES=('a.single.word.argument' 'a multi-word argument' '/some/other/argument' 'yet another')
kill_processes_that_match_arguments "${KILL_THESE_PROCESSES[@]}"
来源:https://stackoverflow.com/questions/10062420/pass-multi-word-arguments-to-a-bash-function