Mam prosty skrypt, w którym pierwszy argument jest zarezerwowany dla nazwy pliku, a wszystkie inne opcjonalne argumenty powinny zostać przekazane do innych części skryptu.
Korzystając z Google, znalazłem tę wiki , ale podałem dosłowny przykład:
echo "${@: -1}"
Nie mogę zmusić niczego innego do pracy, takiego jak:
echo "${@:2}"
lub
echo "${@:2,1}"
Otrzymuję komunikat „Złe zastąpienie” z terminala.
Na czym polega problem i jak mogę przetwarzać wszystkie oprócz pierwszego argumentu przekazanego do skryptu bash?
"{@:2}"
że nie działa, dlatego poprawna odpowiedź pasuje powyżej.Odpowiedzi:
Użyj tego:
Następująca składnia:
działałoby również, ale nie jest zalecane, ponieważ, jak już wyjaśniono @Gordon , że używając
*
, uruchamia wszystkie argumenty razem jako pojedynczy argument ze spacjami,@
zachowując przerwy między nimi (nawet jeśli niektóre same argumenty zawierają spacje ). Nie robi różnicyecho
, ale ma znaczenie dla wielu innych poleceń.źródło
#!/usr/bin/env sh
dlatego miałem problemy. Twój przykład działa dobrze, tak jak powyżej, pod warunkiem, że usunąłem ten shebang"${@:2}"
zamiast tego - użycie*
uruchamia wszystkie argumenty razem jako pojedynczy argument ze spacjami,@
zachowując przerwy między nimi (nawet jeśli same argumenty zawierają spacje). Różnica nie jest zauważalnaecho
, ale ma znaczenie dla wielu innych rzeczy.echo
jest wystarczająco wybaczający, aby połączyć je dla was; inne polecenia mogą nie być tak miłe. Nie używaj tylko jednego lub drugiego: poznaj różnicę między*
i@
i kiedy z nich korzystać. Powinieneś ich używać w równym stopniu. Dobry przykład, kiedy będzie to stanowić problem: jeśli$3
zawiera podział wiersza (\n
), zostanie zastąpiony spacją, pod warunkiem, że masz$IFS
zmienną domyślną .echo
jedynie jako przykład - w takim przypadku powinny one nie być uruchamiane razem. Z mojego doświadczenia wynika , że sytuacje, w których chcesz, aby działały razem, są rzadkie (patrz to pytanie na przykład ) i"$@"
prawie zawsze są tym, czego chcesz. Ponadto problem, o którym wspominasz przy podziale wiersza, występuje tylko wtedy, gdy$@
(lub$*
) nie występuje w cudzysłowie.$*
dość często w moich skryptach.Jeśli potrzebujesz rozwiązania, które działa również w
/bin/sh
tryshift [n]
przesuwa parametry pozycyjne n razy. Ashift
ustawia wartość$1
na wartość$2
, wartość$2
na wartość$3
itd., Zmniejszając wartość o$#
jeden.źródło
foo=shift
nie robi tego, czego się spodziewałam.foo=$(shift)
shift
(w powłoce) nie ma żadnych danych wyjściowych. Po prostu$1
wszystko odrzuca i przesuwa. 2)$(...)
uruchamia podpowłokę, która ma własne lokalne argumenty. Przesuwa argumenty w podpowłoce, co nie wpływa na rodzicasomecommand "$1" "${@:2}"
robi ta metoda (tj. Przesunięcie „inline”)?http://wiki.bash-hackers.org/scripting/posparams
Wyjaśnia użycie
shift
(jeśli chcesz odrzucić pierwsze N parametrów), a następnie implementuje użycie masoweźródło
Natknąłem się na to, szukając czegoś innego. Podczas gdy post wygląda na dość stary, najłatwiejsze rozwiązanie w bash jest zilustrowane poniżej (przynajmniej bash 4),
set -- "${@:#}"
gdzie gdzie # to numer początkowy elementu tablicy, który chcemy zachować do przodu:Zasadniczo, po
set -- "${@:3}"
prostu wyskakuje z pierwszych dwóch elementów w tablicy, takich jak przesunięcie Perla i zachowuje wszystkie pozostałe elementy, w tym trzeci. Podejrzewam, że jest też sposób na zerwanie ostatnich elementów.źródło