开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜