Po pierwsze, pamiętaj, że $@
bez cudzysłowów nie ma sensu i nie należy ich używać. $@
należy używać tylko quoted ( "$@"
) oraz w kontekście listowym.
for i in "$@"
kwalifikuje się jako kontekst listy, ale tutaj, aby zapętlić parametry pozycyjne, kanoniczną, najbardziej przenośną i prostszą formą jest:
for i
do something with "$i"
done
Teraz, aby zapętlić elementy od drugiego, kanonicznym i najbardziej przenośnym sposobem jest użycie shift
:
first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done
Później shift
to, co kiedyś było $1
, zostało usunięte z listy (ale już je zapisaliśmy $first_arg
), a to, co kiedyś było, $2
jest teraz $1
. Parametry pozycji zostały przesunięte 1
w lewo (użyj, shift 2
aby przesunąć o 2 ...). Zasadniczo nasza pętla zapętla się od czegoś, co było drugim argumentem do ostatniego.
Z bash
(i zsh
a ksh93
, ale to wszystko), alternatywą jest do zrobienia:
for i in "${@:2}"
do something with "$i"
done
Należy jednak pamiętać, że nie jest to standardowa sh
składnia, dlatego nie należy jej używać w skrypcie rozpoczynającym się od #! /bin/sh -
.
W zsh
lub yash
możesz także:
for i in "${@[3,-3]}"
do something with "$i"
done
zapętlić od trzeciego do trzeciego argumentu.
W zsh
, $@
jest również znany jako $argv
tablica. Aby wstawiać elementy od początku lub końca tablic, możesz także:
argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()
( shift
Może być również napisany 1=()
w zsh
)
W bash
, można przypisać tylko do $@
elementów z set
wbudowanego polecenia, tak aby pop 3 elementy z końca, to byłoby coś takiego:
set -- "${@:1:$#-3}"
I aby przejść od 3 do 3 ostatniego:
for i in "${@:3:$#-5}"
do something with "$i"
done
POSIXly, aby wyskoczyć 3 ostatnie elementy "$@"
, musisz użyć pętli:
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
Myślę, że chcesz
shift
wbudowany. To zmienia nazwę$2
na$1
,$3
na$2
, itd.Lubię to:
źródło
for
pętlę, a następnie po prostu przechodzisz przez $ @ normalnie. Poshift
połączeniu $ @ powinno byćarg2_1 arg2_2 arg2_3...
Zawsze jest podejście jaskiniowca:
Pozostawia to
$@
nienaruszone (na wypadek, gdybyś chciał użyć go później) i po prostu zapętla każdy argument, ale nie przetwarza pierwszego.źródło
W bash możesz również napisać tę pętlę z jawnym indeksowaniem:
Powtarza to wszystkie argumenty od drugiego do ostatniego. Jeśli zamiast tego chcesz wykluczyć ostatni argument, po prostu to zrób
a jeśli chcesz wziąć co drugi argument, napisz go jako
Historia tego polega na arytmetycznej wersji
for
wbudowanego , w połączeniu z liczbą argumentów$#
i zmienną pośrednią${…}
.Jedną fajną aplikacją jest to, że możesz użyć tego, aby zdecydować w pętli, czy dana opcja będzie przyjmować argument następujący po niej jako wartość. Jeśli tak, zwiększ
i
(np. Zapis: $((++i))
), aby użyć następnej wartości i pomiń ją podczas iteracji.źródło