J'ai besoin d'écrire un script Shell qui s'exécute de cette façon:
./myscript arg1 arg2_1 arg2_2 arg2_3 ....... arg2_#
il y a une boucle for à l'intérieur du script
for i in $@
Cependant, comme je le sais, $ @ comprend 1 $ jusqu'à $ ($ # - 1). Mais pour mon programme, 1 $ est très différent de 2 $ 3 $ 4 $, etc. Je voudrais boucler de 2 $ à la fin ... Comment y arriver? Je vous remercie:)
Tout d'abord, notez que $@
Sans guillemets n'a aucun sens et ne doit pas être utilisé. $@
Ne doit être utilisé qu'entre guillemets ("$@"
) Et dans des contextes de liste.
for i in "$@"
Est considéré comme un contexte de liste, mais ici, pour parcourir les paramètres de position, la forme canonique, la plus portable et la plus simple est:
for i
do something with "$i"
done
Maintenant, pour parcourir les éléments à partir du second, la manière canonique et la plus portable est d'utiliser shift
:
first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done
Après shift
, ce qui était $1
A été supprimé de la liste (mais nous l'avons enregistré dans $first_arg
) Et ce qui était dans $2
est maintenant dans $1
. Les paramètres de position ont été décalé1
Position vers la gauche (utilisez shift 2
Pour décaler de 2 ...). Donc, fondamentalement, notre boucle est en boucle de ce qui était le deuxième argument au dernier.
Avec bash
(et zsh
et ksh93
, Mais c'est tout), une alternative est de faire:
for i in "${@:2}"
do something with "$i"
done
Mais notez que ce n'est pas la syntaxe standard de sh
donc ne doit pas être utilisée dans un script qui commence par #! /bin/sh -
.
Dans zsh
ou yash
, vous pouvez également faire:
for i in "${@[3,-3]}"
do something with "$i"
done
pour boucler du 3ème au 3ème dernier argument.
Dans zsh
, $@
Est également appelé tableau $argv
. Donc, pour faire apparaître des éléments depuis le début ou la fin des tableaux, vous pouvez également faire:
argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()
(shift
peut également être écrit 1=()
dans zsh
)
Dans bash
, vous ne pouvez affecter que les éléments $@
Avec la fonction intégrée set
, donc pour faire sauter 3 éléments à la fin, ce serait quelque chose comme:
set -- "${@:1:$#-3}"
Et pour boucler du 3ème au 3ème dernier:
for i in "${@:3:$#-5}"
do something with "$i"
done
POSIX, pour faire apparaître les 3 derniers éléments de "$@"
, Vous devez utiliser une boucle:
n=$(($# - 3))
for arg do
[ "$n" -gt 0 ] && set -- "$@" "$arg"
shift
n=$((n - 1))
done
Je pense que vous voulez que le shift
soit intégré. Il renomme $2
à $1
, $3
à $2
, etc.
Comme ça:
shift
for i in "$@"; do
echo $i
done
Il y a toujours l'approche des hommes des cavernes:
first=1
for i
do
if [ "$first" ]
then
first=
continue
fi
something with "$i"
done
Cela laisse $@
intact (au cas où vous voudriez l'utiliser plus tard), et boucle simplement sur chaque argument, mais ne traite pas le premier.
En bash, vous pouvez également écrire cette boucle avec une indexation explicite:
for ((i=2; i<=$#; ++i)); do
process "${!i}"
done
Cela itère sur tous les arguments du second au dernier. Si vous souhaitez exclure le dernier argument à la place, faites simplement ceci
for ((i=1; i<=$#-1; ++i)); do
process "${!i}"
done
et si vous voulez seulement prendre tous les autres arguments, écrivez-le
for ((i=1; i<=$#; i+=2)); do
process "${!i}"
done
L'histoire derrière ceci est la version arithmétique du for
builtin , combinée avec le argument-count $#
) = et indirection variable ${…}
.
Une application intéressante est que vous pouvez l'utiliser pour décider, à l'intérieur de la boucle, si une option donnée prendra l'argument qui la suit comme valeur. Si c'est le cas, incrémentez i
(par exemple en écrivant : $((++i))
) pour consommer la valeur suivante et sautez-la pendant l'itération.