Ich habe ein einfaches Skript, in dem das erste Argument für den Dateinamen reserviert ist und alle anderen optionalen Argumente an andere Teile des Skripts übergeben werden sollten.
Mit Google habe ich dieses Wiki gefunden , aber es lieferte ein wörtliches Beispiel:
echo "${@: -1}"
Ich kann nichts anderes zum Arbeiten bringen, wie:
echo "${@:2}"
oder
echo "${@:2,1}"
Ich bekomme "Bad Substitution" vom Terminal.
Was ist das Problem und wie kann ich alle bis auf das erste an ein Bash-Skript übergebenen Argument verarbeiten?
"{@:2}"
, dass er nicht funktionierte, weshalb die richtige Antwort oben übereinstimmt.Antworten:
Benutze das:
Die folgende Syntax:
würde auch funktionieren, wird aber nicht empfohlen, da, wie @Gordon bereits erklärt hat, bei der Verwendung
*
alle Argumente zusammen als ein einziges Argument mit Leerzeichen ausgeführt werden, während@
die Unterbrechungen zwischen ihnen beibehalten werden (auch wenn einige der Argumente selbst Leerzeichen enthalten ). Es macht keinen Unterschied mitecho
, aber es ist wichtig für viele andere Befehle.quelle
#!/usr/bin/env sh
Deshalb hatte ich Probleme. Ihr Beispiel funktioniert gut, wie oben angegeben, nachdem ich diesen Shebang"${@:2}"
stattdessen - using*
führt alle Argumente zusammen als ein einziges Argument mit Leerzeichen aus, wobei@
die Unterbrechungen zwischen ihnen beibehalten werden (auch wenn einige der Argumente selbst Leerzeichen enthalten). Der Unterschied ist bei nicht spürbarecho
, aber für viele andere Dinge von Bedeutung.echo
verzeiht genug, um sie für Sie zu verketten; andere Befehle sind möglicherweise nicht so nett. Verwenden Sie nicht nur das eine oder andere: Lernen Sie den Unterschied zwischen*
und@
und wann Sie jedes verwenden müssen. Sie sollten sie ungefähr gleich verwenden. Ein gutes Beispiel dafür, wann dies ein Problem sein wird: Wenn es$3
einen Zeilenumbruch (\n
) enthält, wird dieser durch ein Leerzeichen ersetzt, sofern Sie eine Standardvariable haben$IFS
.echo
nur als Beispiel dient. In diesem Fall sollten sie nicht zusammen ausgeführt werden. Nach meiner Erfahrung sind Situationen, in denen Sie möchten, dass sie zusammen ausgeführt werden, selten (siehe diese Frage für ein Beispiel ) und"$@"
fast immer das, was Sie möchten. Das Problem, das Sie bei einem Zeilenumbruch erwähnen, tritt nur auf, wenn$@
(oder$*
) nicht in doppelte Anführungszeichen steht.$*
ziemlich oft in meinen Skripten verwenden.Wenn Sie eine Lösung
/bin/sh
suchen , die auch funktioniert, versuchen Sie esshift [n]
verschiebt die Positionsparameter n- mal. Ashift
setzt den Wert von$1
auf den Wert von$2
, den Wert von$2
auf den Wert von$3
usw. und verringert den Wert von$#
um eins.quelle
foo=shift
nicht das, was ich erwarten würde.foo=$(shift)
shift
(in der Shell) hat keine Ausgabe. Es wirft einfach$1
alles weg und verschiebt es nach unten. 2)$(...)
Startet eine Subshell, die ihre eigenen lokalen Argumente hat. Es verschiebt die Argumente in der Unterschale, was die Eltern nicht betrifftsomecommand "$1" "${@:2}"
mit dieser Methode zu tun ist (dh "inline" verschieben)?http://wiki.bash-hackers.org/scripting/posparams
Es wird die Verwendung von
shift
(wenn Sie die ersten N Parameter verwerfen möchten) und die anschließende Implementierung von Mass Usage erläutertquelle
Kam über diese Suche nach etwas anderem. Während der Beitrag ziemlich alt aussieht, wird die einfachste Lösung in Bash unten dargestellt (mindestens Bash 4),
set -- "${@:#}"
wobei # die Startnummer des Array-Elements ist, das wir vorwärts beibehalten möchten:Grundsätzlich
set -- "${@:3}"
werden die ersten beiden Elemente im Array wie die Perl- Verschiebung einfach entfernt und alle verbleibenden Elemente einschließlich des dritten beibehalten. Ich vermute, es gibt auch eine Möglichkeit, die letzten Elemente zu entfernen.quelle