Delete positional parameters in Bash?
You can skip positional parameters with shift
but can you delete positional parameters by passing the position?
x(){ CODE; echo "$@"; }; x 1 2 3 4 5 6 7 8
> 1 2 4 5 6 7 8
I would like to add CODE to x()
to delete positional parameter 3. I don't want to do echo "${@:1:2} ${@:4:8}"
. After running CODE, $@
should only conta开发者_开发技巧in "1 2 4 5 6 7 8".
The best way, if you want to be able to pass on the parameters to another process, or handle space separated parameters, is to re-set
the parameters:
$ x(){ echo "Parameter count before: $#"; set -- "${@:1:2}" "${@:4:8}"; echo "$@"; echo "Parameter count after: $#"; }
$ x 1 2 3 4 5 6 7 8
Parameter count before: 8
1 2 4 5 6 7 8
Parameter count after: 7
To test that it works with non-trivial parameters:
$ x $'a\n1' $'b\b2' 'c 3' 'd 4' 'e 5' 'f 6' 'g 7' $'h\t8'
Parameter count before: 8
a
1 2 d 4 e 5 f 6 g 7 h 8
Parameter count after: 7
(Yes, $'\b'
is a backspace)
x(){
#CODE
params=( $* )
unset params[2]
set -- "${params[@]}"
echo "$@"
}
Input: x 1 2 3 4 5 6 7 8
Output: 1 2 4 5 6 7 8
From tldp
# The "unset" command deletes elements of an array, or entire array.
unset colors[1] # Remove 2nd element of array.
# Same effect as colors[1]=
echo ${colors[@]} # List array again, missing 2nd element.
unset colors # Delete entire array.
# unset colors[*] and
#+ unset colors[@] also work.
echo; echo -n "Colors gone."
echo ${colors[@]} # List array again, now empty.
You can call set and reset the positional paramaters at any time for example
function q {
echo ${@}
set $2 $3 $4
echo ${@}
set $4
echo ${@}
}
q 1 2 3 4
then slice out what you dont want from the array, the below code does that... not sure if its the best way to do it though, was on stack looking for a better way ; )
#!/bin/bash
q=( one two three four five )
echo -e "
(remove) { [:range:] } <- [:list:]
| [:range:] => return list with range removed range is in the form of [:digit:]-[:digit:]
"
function remove {
if [[ $1 =~ ([[:digit:]])(-([[:digit:]]))? ]]; then
from=${BASH_REMATCH[1]}
to=${BASH_REMATCH[3]}
else
echo bad range
fi;shift
array=( ${@} )
local start=${array[@]::${from}}
local rest
[ -n "$to" ] && rest=${array[@]:((${to}+1))} || rest=${array[@]:((${from}+1))}
echo ${start[@]} ${rest[@]}
}
q=( `remove 1 ${q[*]}` )
echo ${q[@]}
while loop over "$@" with shift + set: move each parameter from first to last position, except "test"
# remove option "test" from positional parameters
i=1
while [ $i -le $# ]
do
var="$1"
case "$var" in
test)
echo "param \"$var\" deleted"
i=$(($i-1))
;;
*)
set -- "$@" "$var"
;;
esac
shift
i=$(($i+1))
done
精彩评论