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