Primeiro, observe que $@ sem aspas não faz sentido e não deve ser usado. $@ só deve ser usado entre aspas ( "$@" ) e em contextos de lista.
for i in "$@" se qualifica como um contexto de lista, mas aqui, para fazer um loop sobre os parâmetros posicionais, a forma canônica, mais portátil e mais simples é:
for i
do something with "$i"
done
Agora, para percorrer os elementos a partir do segundo, a maneira mais canônica e mais portátil é usar shift :
first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done
Depois de shift , o que costumava ser $1 foi removido da lista (mas o salvamos em $first_arg ) e o que costumava estar em $2 agora está em $1 . Os parâmetros posicionais foram alterados 1 position para a esquerda (use shift 2 para mudar em 2 ...). Então, basicamente, nosso loop está em loop do que costumava ser o segundo argumento para o último.
Com bash (e zsh e ksh93 , mas é isso), uma alternativa é fazer:
for i in "${@:2}"
do something with "$i"
done
Mas observe que não é a sintaxe sh padrão, portanto, não deve ser usada em um script que comece com #! /bin/sh - .
Em zsh ou yash , você também pode fazer:
for i in "${@[3,-3]}"
do something with "$i"
done
para fazer um loop do terceiro ao terceiro último argumento.
Em zsh , $@ também é conhecido como o array $argv . Então, para pop elementos a partir do começo ou fim dos arrays, você também pode fazer:
argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()
( shift também pode ser escrito 1=() in zsh )
Em bash , você só pode atribuir aos elementos $@ com o set incorporado, então, para inserir três elementos no final, seria algo como:
set -- "${@:1:$#-3}"
E para fazer o loop do terceiro ao terceiro último:
for i in "${@:3:$#-5}"
do something with "$i"
done
POSIXly, para inserir os últimos 3 elementos de "$@" , você precisaria usar um loop:
n=$(($# - 3))
for arg do
[ "$n" -gt 0 ] && set -- "$@" "$arg"
shift
n=$((n - 1))
done