Primero, tenga en cuenta que $@
sin comillas no tiene sentido y no debe usarse. $@
solo debe usarse entre comillas ( "$@"
) y en contextos de lista.
for i in "$@"
califica como un contexto de lista, pero aquí, para recorrer los parámetros posicionales, la forma canónica, más portátil y más simple es:
for i
do something with "$i"
done
Ahora, para recorrer los elementos a partir del segundo, la forma canónica y más portátil es usar shift
:
first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done
Después shift
, lo que solía ser $1
se ha eliminado de la lista (pero lo hemos guardado $first_arg
) y lo que solía estar $2
ahora está dentro $1
. Los parámetros posicionales se han desplazado 1
hacia la izquierda (se usa shift 2
para cambiar por 2 ...). Básicamente, nuestro bucle se repite desde lo que solía ser el segundo argumento hasta el último.
Con bash
(y zsh
y ksh93
, pero eso es todo), una alternativa es hacer:
for i in "${@:2}"
do something with "$i"
done
Pero tenga en cuenta que no es una sh
sintaxis estándar, por lo que no debe usarse en un script que comience con #! /bin/sh -
.
En zsh
o yash
, también puedes hacer:
for i in "${@[3,-3]}"
do something with "$i"
done
pasar del 3er al 3er último argumento.
En zsh
, $@
también se conoce como la $argv
matriz. Entonces, para resaltar elementos desde el principio o el final de las matrices, también puede hacer:
argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()
( shift
también se puede escribir 1=()
en zsh
)
En bash
, solo puede asignar a los $@
elementos con la función set
incorporada, por lo que sacar 3 elementos del final, sería algo así como:
set -- "${@:1:$#-3}"
Y para pasar del 3 al 3 último:
for i in "${@:3:$#-5}"
do something with "$i"
done
POSIXY, para hacer estallar los últimos 3 elementos de "$@"
, necesitaría usar un bucle:
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
Creo que quieres el
shift
incorporado. Renombra$2
a$1
,$3
a$2
, etc.Me gusta esto:
fuente
for
ciclo, luego simplemente recorre $ @ normalmente. Después de lashift
llamada, $ @ debería serarg2_1 arg2_2 arg2_3...
Siempre existe el enfoque del hombre de las cavernas:
Esto deja
$@
intacto (en caso de que quiera usarlo más tarde), y simplemente recorre cada argumento, pero no procesa el primero.fuente
En bash también puedes escribir ese ciclo con indexación explícita:
Esto itera sobre todos los argumentos desde el segundo hasta el último. Si desea excluir el último argumento, simplemente haga esto
y si solo quieres tomar cualquier otro argumento, escríbelo como
La historia detrás de esto es la versión aritmética de la
for
construcción , combinada con el conteo de argumentos$#
y la indirección variable${…}
.Una buena aplicación es que puede usar esto para decidir, dentro del ciclo, si una opción dada tomará el argumento que le sigue como un valor. Si lo hace, incremente
i
(por ejemplo, escribir: $((++i))
) para consumir el siguiente valor y omítalo durante la iteración.fuente