Primeiro, observe que $@
sem aspas não faz sentido e não deve ser usado. $@
deve ser usado apenas 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 canônica e mais portátil é usar shift
:
first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done
Depois shift
, o que costumava ser $1
foi removido da lista (mas salvou-lo em $first_arg
) eo que costumava ser no $2
agora está em $1
. Os parâmetros posicionais foram trocados de 1
posição para a esquerda (use shift 2
para deslocar 2 ...). Então, basicamente, nosso loop está repetindo o que costumava ser o segundo argumento até 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 é uma sh
sintaxe padrão, portanto, não deve ser usado em um script que comece com #! /bin/sh -
.
Em zsh
ou yash
, você também pode:
for i in "${@[3,-3]}"
do something with "$i"
done
para fazer um loop do terceiro para o terceiro último argumento.
In zsh
, $@
também é conhecido como $argv
array. Portanto, para exibir elementos do início ou do fim das matrizes, você também pode:
argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()
( shift
também pode ser escrito 1=()
em zsh
)
Em bash
, você só pode atribuir aos $@
elementos com o set
builtin, para destacar três elementos no final, isso seria algo como:
set -- "${@:1:$#-3}"
E para passar do terceiro para o terceiro último:
for i in "${@:3:$#-5}"
do something with "$i"
done
POSIX, para exibir os três últimos elementos "$@"
, você precisará usar um loop:
n=$(($# - 3))
for arg do
[ "$n" -gt 0 ] && set -- "$@" "$arg"
shift
n=$((n - 1))
done
for ((i=2; i<=$#; i++)); do something with "${!i}"; done
Eu acho que você quer o
shift
embutido. Renomeia$2
para$1
,$3
para$2
etc.Como isso:
fonte
for
loop, então apenas repassa $ @ normalmente. Após ashift
chamada, $ @ deve serarg2_1 arg2_2 arg2_3...
Sempre há a abordagem do homem das cavernas:
Isso deixa
$@
intacto (caso você queira usá-lo posteriormente) e simplesmente faz um loop sobre todos os argumentos, mas não processa o primeiro.fonte
No bash, você também pode escrever esse loop com indexação explícita:
Isso itera sobre todos os argumentos do segundo ao último. Se você deseja excluir o último argumento, basta fazer isso
e se você quiser apenas usar todos os outros argumentos, escreva-o como
A história por trás disso é a versão aritmética do
for
builtin , combinada com a contagem de argumentos$#
e a variável indireta${…}
.Uma boa aplicação é que você pode usar isso para decidir, dentro do loop, se uma determinada opção aceita o argumento que segue como um valor. Se isso acontecer, incremente
i
(por exemplo, gravação: $((++i))
) para consumir o próximo valor e pule-o durante a iteração.fonte