Denn nur bash , die Kevin Kleine Antwort schlägt vor , die einfach ${!#}. Testen Sie es mit bash -c 'echo ${!#}' arg1 arg2 arg3. Für bash , ksh und zsh , die Dennis Williamson Antwort schlägt ${@: -1}. Darüber hinaus ${*: -1}kann auch verwendet werden. Testen Sie es mit zsh -c 'echo ${*: -1}' arg1 arg2 arg3. Dies funktioniert jedoch nicht für dash , csh und tcsh .
Olibre
2
${!#}${@: -1}funktioniert im Gegensatz dazu auch mit Parametererweiterung. Sie können es mit testen bash -c 'echo ${!#%.*}' arg1.out arg2.out arg3.out.
Arch Stanton
Antworten:
177
Das ist ein bisschen wie ein Hack:
for last;do true;done
echo $last
Dieser ist auch ziemlich portabel (sollte wieder mit bash, ksh und sh funktionieren) und verschiebt die Argumente nicht, was nett sein könnte.
Es wird die Tatsache verwendet, dass fordie Argumente implizit durchlaufen werden, wenn Sie nicht angeben, was durchlaufen werden soll, und die Tatsache, dass for-Schleifenvariablen keinen Gültigkeitsbereich haben: Sie behalten den letzten Wert bei, auf den sie festgelegt wurden.
Mit einem alten Solaris, mit der alten Bourne-Shell (nicht POSIX), muss ich "zum
Schluss
8
@mcoolive @LaurenceGolsalves ist nicht nur portabler, sondern for last in "$@"; do :; donemacht auch die Absicht viel klarer.
Adrian Günter
1
@mcoolive: Es funktioniert sogar in der Unix v7 bourne Shell von 1979. Sie können nicht portabler werden, wenn es sowohl auf v7 sh als auch auf POSIX sh läuft :)
Für diejenigen (wie ich), die sich fragen, warum der Platz benötigt wird, hat man bash folgendes zu sagen:> Beachten Sie, dass ein negativer Versatz durch mindestens ein Leerzeichen vom Doppelpunkt getrennt sein muss, um nicht mit der folgenden Erweiterung verwechselt zu werden: -.
foo
1
Ich habe dies verwendet und es bricht in MSYS2 Bash nur in Windows. Bizarr.
Steven Lu
2
Hinweis: Diese Antwort funktioniert für alle Bash-Arrays, anders als ${@:$#}nur für $@. Wenn Sie mit $@in ein neues Array kopieren würden arr=("$@"), ${arr[@]:$#}wäre dies undefiniert. Dies liegt daran, dass $@es ein 0. Element gibt, das nicht in "$@"Erweiterungen enthalten ist.
Mr. Llama
@ Mr.Llama: Ein weiterer Punkt, den Sie vermeiden sollten, $#ist das Iterieren über Arrays, da Arrays in Bash spärlich sind und zwar $#die Anzahl der Elemente im Array anzeigen, aber nicht unbedingt auf das letzte Element (oder Element + 1) zeigen. Mit anderen Worten, man sollte die Indizes nicht tun for ((i = 0; i++; i < $#)); do something "${array[$i]}"; doneund stattdessen for element in "${array[@]}"; do something "$element"; donedurchlaufen oder durchlaufen: for index in "${!array[@]}"; do something "$index" "${array[$index]}"; donewenn Sie etwas mit den Werten der Indizes tun müssen.
Bis auf weiteres angehalten.
80
$ set quick brown fox jumps
$ echo ${*:-1:1}# last argument
jumps
$ echo ${*:-1}# or simply
jumps
$ echo ${*:-2:1}# next to last
fox
Der Speicherplatz ist erforderlich, damit er nicht als Standardwert interpretiert wird .
Beste Antwort, da es auch das vorletzte Argument enthält. Vielen Dank!
e40
1
Steven, ich weiß nicht, was du getan hast, um in der Strafbank zu landen, aber ich liebe deine Arbeit hier.
Bruno Bronosky
4
Ja. einfach das beste. alle außer Befehl und letztes Argument ${@: 1:$#-1}
Dyno Fu
1
@ DynoFu danke dafür, du hast meine nächste Frage beantwortet. Eine Verschiebung könnte also so aussehen: echo ${@: -1} ${@: 1:$#-1}Wo zuletzt zuerst wird und der Rest nach unten rutscht
Mike
73
Die einfachste Antwort für Bash 3.0 oder höher ist
_last=${!#}# *indirect reference* to the $# variable# or
_last=$BASH_ARGV # official built-in (but takes more typing :)
Das ist es.
$ cat lastarg
#!/bin/bash# echo the last arg given:
_last=${!#}
echo $_last
_last=$BASH_ARGV
echo $_last
for x;do
echo $x
done
$BASH_ARGVfunktioniert nicht innerhalb einer Bash-Funktion (es sei denn, ich mache etwas falsch).
Big McLargeHuge
1
Der BASH_ARGV hat die Argumente, als bash aufgerufen wurde (oder eine Funktion), nicht die aktuelle Liste der Positionsargumente.
Isaac
Beachten Sie auch BASH_ARGV, dass Sie den Wert erhalten, der als letztes Argument angegeben wurde, anstatt einfach "den letzten Wert". Zum Beispiel!: Wenn Sie ein einzelnes Argument angeben, dann rufen Sie shift auf, ${@:$#}erzeugen nichts (weil Sie das einzige Argument verschoben haben!), BASH_ARGVGeben Ihnen jedoch immer noch das (früher) letzte Argument.
Steven Lu
30
Verwenden Sie die Indizierung kombiniert mit der Länge von:
Folgendes wird für Sie funktionieren. Das @ steht für ein Array von Argumenten. : bedeutet bei. $ # ist die Länge des Array von Argumenten. Das Ergebnis ist also das letzte Element:
${@:$#}
Beispiel:
function afunction{
echo ${@:$#} }
afunction -d -o local50#Outputs 50
Während das Beispiel für eine Funktion ist, funktionieren Skripte auf die gleiche Weise. Ich mag diese Antwort, weil sie klar und prägnant ist.
Jonah Braun
1
Und es ist nicht hacky. Es werden explizite Merkmale der Sprache verwendet, keine Nebenwirkungen oder spezielle Qwerks. Dies sollte die akzeptierte Antwort sein.
musicin3d
25
Ich habe dies gefunden, als ich versucht habe, das letzte Argument von allen vorherigen zu trennen. Während einige der Antworten das letzte Argument erhalten, sind sie nicht sehr hilfreich, wenn Sie auch alle anderen Argumente benötigen. Das funktioniert viel besser:
Die Antwort des Steven Penny ist ein bisschen schöner: Verwendung ${@: -1}für letzte und ${@: -2:1}für vorletzter (und so weiter ...). Beispiel: bash -c 'echo ${@: -1}' prog 0 1 2 3 4 5 6Drucke 6. Um bei diesem aktuellen Ansatz von AgileZebra zu bleiben, verwenden Sie ${@:$#-1:1}, um den vorletzten zu erhalten . Beispiel: bash -c 'echo ${@:$#-1:1}' prog 0 1 2 3 4 5 6Drucke 5. (und ${@:$#-2:1}um den drittletzten zu bekommen und so weiter ...)
Olibre
4
Die Antwort von AgileZebra bietet eine Möglichkeit, alle bis auf die letzten Argumente zu erhalten, sodass ich nicht sagen würde, dass die Antwort von Steven sie ersetzt. Es scheint jedoch keinen Grund zu geben $((...)), die 1 zu subtrahieren. Sie können sie einfach verwenden ${@:1:$# - 1}.
Dkasak
Danke dkasak. Aktualisiert, um Ihre Vereinfachung widerzuspiegeln.
AgileZebra
22
Dies funktioniert in allen POSIX-kompatiblen Shells:
Die einfachste tragbare Lösung, die ich hier sehe. Dieser hat kein Sicherheitsproblem, @DennisWilliamson, das empirische Zitieren scheint richtig zu sein, es sei denn, es gibt eine Möglichkeit $#, eine beliebige Zeichenfolge festzulegen (ich glaube nicht). eval last=\"\${$#}\"funktioniert auch und ist offensichtlich richtig. Sehen Sie nicht, warum die Anführungszeichen nicht benötigt werden.
Palec
1
Für bash ist zsh , dash und ksheval last=\"\${$#}\" in Ordnung. Aber für csh und tcsh verwenden eval set last=\"\${$#}\". Siehe dieses Beispiel : tcsh -c 'eval set last=\"\${$#}\"; echo "$last"' arg1 arg2 arg3.
Olibre
12
Hier ist meine Lösung:
ziemlich portabel (alle POSIX sh, bash, ksh, zsh) sollte funktionieren
verschiebt nicht die ursprünglichen Argumente (verschiebt eine Kopie).
Tolle Antwort - kurz, tragbar, sicher. Vielen Dank!
Ján Lalinský
2
Dies ist eine großartige Idee, aber ich habe ein paar Vorschläge: Erstens zitiert sowohl um hinzugefügt werden soll "$1"und "$#"(diese große Antwort unix.stackexchange.com/a/171347 ). Zweitens echoist leider nicht tragbar (insbesondere für -n), printf '%s\n' "$1"sollte also stattdessen verwendet werden.
Joki
danke @joki Ich habe mit vielen verschiedenen Unix-Systemen gearbeitet und würde auch nicht vertrauen echo -n, aber mir ist nicht bekannt, auf welchem Posix-System ein Fehler auftreten echo "$1"würde. Jedenfalls printfist in der Tat vorhersehbarer - aktualisiert.
Michał Šrajer
@ MichałŠrajer betrachten den Fall , in dem „$ 1“ „-n“ oder „-“ ist , so zum Beispiel ntharg 1 -noder ntharg 1 --können unterschiedliche Ergebnisse auf verschiedenen Systemen ergeben. Der Code, den Sie jetzt haben, ist sicher!
Joki
10
Von den ältesten zu den neueren Lösungen:
Die tragbarste Lösung, auch älter sh(funktioniert mit Leerzeichen und Glob-Zeichen) (keine Schleife, schneller):
eval printf "'%s\n'""\"\${$#}\""
Seit Version 2.01 von bash
$ set--The quick brown fox jumps over the lazy dog
$ printf '%s\n'"${!#} ${@:(-1)} ${@: -1} ${@:~0} ${!#}"
dog dog dog dog dog
Für ksh, zsh und bash:
$ printf '%s\n'"${@: -1} ${@:~0}"# the space beetwen `:`# and `-1` is a must.
dog dog
Und für "vorletzte":
$ printf '%s\n'"${@:~1:1}"
lazy
Verwenden von printf, um Probleme mit Argumenten zu umgehen, die mit einem Bindestrich beginnen (z -n ).
Für alle Shells und für ältere sh(funktioniert mit Leerzeichen und Glob-Zeichen) gilt:
$ set--The quick brown fox jumps over the lazy dog "the * last argument"
$ eval printf "'%s\n'""\"\${$#}\""The last * argument
Oder wenn Sie eine Variable festlegen möchten last:
$ eval last=\${$#}; printf '%s\n' "$last"The last * argument
Dies verschiebt die Argumente um die Anzahl der Argumente minus 1 und gibt das erste (und einzige) verbleibende Argument zurück, das das letzte sein wird.
Ich habe nur in Bash getestet, aber es sollte auch in Sh und Ksh funktionieren.
shift $(($# - 1))- Keine Notwendigkeit für ein externes Dienstprogramm. Funktioniert in Bash, ksh, zsh und dash.
Bis auf weiteres angehalten.
@ Tennis: Schön! Ich wusste nichts über die $((...))Syntax.
Laurence Gonsalves
Sie möchten verwenden printf '%s\n' "$1", um unerwartetes Verhalten von echo(z -n. B. für ) zu vermeiden .
Joki
2
Wenn Sie dies zerstörungsfrei tun möchten, besteht eine Möglichkeit darin, alle Argumente an eine Funktion zu übergeben und das letzte zurückzugeben:
#!/bin/bash
last(){if[[ $# -ne 0 ]] ; then
shift $(expr $# - 1)
echo "$1"#else#do something when no argumentsfi}
lastvar=$(last "$@")
echo $lastvar
echo "$@"
pax>./qq.sh 123 a b
b
123 a b
Wenn es dich eigentlich nicht interessiert , die anderen Argumente beizubehalten, brauchen Sie sie nicht in einer Funktion, aber es fällt mir schwer, an eine Situation zu denken, in der Sie die anderen Argumente niemals behalten möchten, es sei denn, sie wurden bereits verarbeitet. In diesem Fall würde ich die Methode process / shift / process / shift / ... verwenden, um sie nacheinander zu verarbeiten.
Ich gehe hier davon aus, dass Sie sie behalten möchten, weil Sie die sequentielle Methode nicht befolgt haben . Diese Methode behandelt auch den Fall, dass keine Argumente vorhanden sind und "" zurückgegeben werden. Sie können dieses Verhalten leicht anpassen, indem Sie die auskommentierte elseKlausel einfügen .
Ich weiß, dass Sie dies für immer gepostet haben, aber diese Lösung ist großartig - ich bin froh, dass jemand eine tcsh gepostet hat!
user3295674
2
Ich fand die Antwort von @ AgileZebra (plus den Kommentar von @ starfry) am nützlichsten, aber sie setzt headsauf einen Skalar. Ein Array ist wahrscheinlich nützlicher:
eval für indirekte Referenz ist übertrieben, nicht schlecht Praxis zu erwähnen, und ein riesiges Sicherheitsproblem (der Wert ist nicht Zitat in Echo oder außerhalb $ () Bash hat einen eingebauten Syntax für indirekte Verweis, für jede var. !So last="${!#}"würde verwendet die gleiche Ansatz (indirekte Referenz auf $ #) in einer viel sichereren, kompakteren, eingebauten, vernünftigen Weise. Und richtig zitiert.
MestreLion
Sehen Sie in einer anderen Antwort einen saubereren Weg, um dasselbe zu tun .
Palec
@ MestreLion-Anführungszeichen werden auf der rechten Seite von nicht benötigt =.
Tom Hale
1
@TomHale: true für den speziellen Fall von ${!#}, aber nicht allgemein: Anführungszeichen werden weiterhin benötigt, wenn der Inhalt wörtliche Leerzeichen enthält, z last='two words'. Nur $()ist Leerzeichen sicher, unabhängig vom Inhalt.
MestreLion
1
Nachdem ich die obigen Antworten gelesen hatte, schrieb ich ein Q & D-Shell-Skript (sollte mit sh und bash funktionieren), um g ++ auf PGM.cpp auszuführen und ein ausführbares Image-PGM zu erstellen. Es wird davon ausgegangen, dass das letzte Argument in der Befehlszeile der Dateiname ist (.cpp ist optional) und alle anderen Argumente Optionen sind.
#!/bin/shif[ $# -lt 1 ]then
echo "Usage: `basename $0` [opt] pgm runs g++ to compile pgm[.cpp] into pgm"
exit 2fi
OPT=
PGM=# PGM is the last argument, all others are considered optionsfor F;do OPT="$OPT $PGM"; PGM=$F;done
DIR=`dirname $PGM`
PGM=`basename $PGM .cpp`# put -o first so it can be overridden by -o specified in OPTset-x
g++-o $DIR/$PGM $OPT $DIR/$PGM.cpp
Der Eval-Ansatz wurde hier bereits viele Male vorgestellt, aber dieser hat eine Erklärung, wie er funktioniert. Könnte weiter verbessert werden, aber es lohnt sich immer noch, es zu behalten.
Ich vermute, dass dies mit ./arguments.sh "letzter Wert"
Thomas
Vielen Dank, dass Sie Thomas überprüft haben. Ich habe versucht, das as-Skript so auszuführen, wie Sie es mit # ./arguments.sh "last value" angegeben haben. Das letzte Argument lautet: value funktioniert jetzt einwandfrei. # ./arguments.sh "letzte Wertprüfung mit double" Letztes Argument ist: double
Ranjithkumar T
Das Problem ist, dass das letzte Argument 'letzter Wert' und nicht Wert war. Der Fehler wird durch das Argument verursacht, das ein Leerzeichen enthält.
Thomas
0
Es gibt einen viel prägnanteren Weg, dies zu tun. Argumente für ein Bash-Skript können in ein Array eingefügt werden, was den Umgang mit den Elementen erheblich vereinfacht. Das folgende Skript gibt immer das letzte Argument aus, das an ein Skript übergeben wurde.
argArray=("$@")# Add all script arguments to argArray
arrayLength=${#argArray[@]}# Get the length of the array
lastArg=$((arrayLength -1))# Arrays are zero based, so last arg is -1
echo ${argArray[$lastArg]}
${!#}
. Testen Sie es mitbash -c 'echo ${!#}' arg1 arg2 arg3
. Für bash , ksh und zsh , die Dennis Williamson Antwort schlägt${@: -1}
. Darüber hinaus${*: -1}
kann auch verwendet werden. Testen Sie es mitzsh -c 'echo ${*: -1}' arg1 arg2 arg3
. Dies funktioniert jedoch nicht für dash , csh und tcsh .${!#}
${@: -1}
funktioniert im Gegensatz dazu auch mit Parametererweiterung. Sie können es mit testenbash -c 'echo ${!#%.*}' arg1.out arg2.out arg3.out
.Antworten:
Das ist ein bisschen wie ein Hack:
Dieser ist auch ziemlich portabel (sollte wieder mit bash, ksh und sh funktionieren) und verschiebt die Argumente nicht, was nett sein könnte.
Es wird die Tatsache verwendet, dass
for
die Argumente implizit durchlaufen werden, wenn Sie nicht angeben, was durchlaufen werden soll, und die Tatsache, dass for-Schleifenvariablen keinen Gültigkeitsbereich haben: Sie behalten den letzten Wert bei, auf den sie festgelegt wurden.quelle
true
ist Teil von POSIX .for last in "$@"; do :; done
macht auch die Absicht viel klarer.Dies ist nur Bash:
quelle
${@:$#}
nur für$@
. Wenn Sie mit$@
in ein neues Array kopieren würdenarr=("$@")
,${arr[@]:$#}
wäre dies undefiniert. Dies liegt daran, dass$@
es ein 0. Element gibt, das nicht in"$@"
Erweiterungen enthalten ist.$#
ist das Iterieren über Arrays, da Arrays in Bash spärlich sind und zwar$#
die Anzahl der Elemente im Array anzeigen, aber nicht unbedingt auf das letzte Element (oder Element + 1) zeigen. Mit anderen Worten, man sollte die Indizes nicht tunfor ((i = 0; i++; i < $#)); do something "${array[$i]}"; done
und stattdessenfor element in "${array[@]}"; do something "$element"; done
durchlaufen oder durchlaufen:for index in "${!array[@]}"; do something "$index" "${array[$index]}"; done
wenn Sie etwas mit den Werten der Indizes tun müssen.Der Speicherplatz ist erforderlich, damit er nicht als Standardwert interpretiert wird .
Beachten Sie, dass dies nur Bash ist.
quelle
${@: 1:$#-1}
echo ${@: -1} ${@: 1:$#-1}
Wo zuletzt zuerst wird und der Rest nach unten rutschtDie einfachste Antwort für Bash 3.0 oder höher ist
Das ist es.
Ausgabe ist:
quelle
$BASH_ARGV
funktioniert nicht innerhalb einer Bash-Funktion (es sei denn, ich mache etwas falsch).BASH_ARGV
, dass Sie den Wert erhalten, der als letztes Argument angegeben wurde, anstatt einfach "den letzten Wert". Zum Beispiel!: Wenn Sie ein einzelnes Argument angeben, dann rufen Sie shift auf,${@:$#}
erzeugen nichts (weil Sie das einzige Argument verschoben haben!),BASH_ARGV
Geben Ihnen jedoch immer noch das (früher) letzte Argument.Verwenden Sie die Indizierung kombiniert mit der Länge von:
Beachten Sie, dass dies nur Bash ist.
quelle
echo ${@:$#}
Folgendes wird für Sie funktionieren. Das @ steht für ein Array von Argumenten. : bedeutet bei. $ # ist die Länge des Array von Argumenten. Das Ergebnis ist also das letzte Element:
Beispiel:
Beachten Sie, dass dies nur Bash ist.
quelle
Ich habe dies gefunden, als ich versucht habe, das letzte Argument von allen vorherigen zu trennen. Während einige der Antworten das letzte Argument erhalten, sind sie nicht sehr hilfreich, wenn Sie auch alle anderen Argumente benötigen. Das funktioniert viel besser:
Beachten Sie, dass dies nur Bash ist.
quelle
${@: -1}
für letzte und${@: -2:1}
für vorletzter (und so weiter ...). Beispiel:bash -c 'echo ${@: -1}' prog 0 1 2 3 4 5 6
Drucke6
. Um bei diesem aktuellen Ansatz von AgileZebra zu bleiben, verwenden Sie${@:$#-1:1}
, um den vorletzten zu erhalten . Beispiel:bash -c 'echo ${@:$#-1:1}' prog 0 1 2 3 4 5 6
Drucke5
. (und${@:$#-2:1}
um den drittletzten zu bekommen und so weiter ...)$((...))
, die 1 zu subtrahieren. Sie können sie einfach verwenden${@:1:$# - 1}
.Dies funktioniert in allen POSIX-kompatiblen Shells:
Quelle: http://www.faqs.org/faqs/unix-faq/faq/part2/section-12.html
quelle
$#
, eine beliebige Zeichenfolge festzulegen (ich glaube nicht).eval last=\"\${$#}\"
funktioniert auch und ist offensichtlich richtig. Sehen Sie nicht, warum die Anführungszeichen nicht benötigt werden.eval last=\"\${$#}\"
in Ordnung. Aber für csh und tcsh verwendeneval set last=\"\${$#}\"
. Siehe dieses Beispiel :tcsh -c 'eval set last=\"\${$#}\"; echo "$last"' arg1 arg2 arg3
.Hier ist meine Lösung:
Böse nichteval
Code:
quelle
"$1"
und"$#"
(diese große Antwort unix.stackexchange.com/a/171347 ). Zweitensecho
ist leider nicht tragbar (insbesondere für-n
),printf '%s\n' "$1"
sollte also stattdessen verwendet werden.echo -n
, aber mir ist nicht bekannt, auf welchem Posix-System ein Fehler auftretenecho "$1"
würde. Jedenfallsprintf
ist in der Tat vorhersehbarer - aktualisiert.ntharg 1 -n
oderntharg 1 --
können unterschiedliche Ergebnisse auf verschiedenen Systemen ergeben. Der Code, den Sie jetzt haben, ist sicher!Von den ältesten zu den neueren Lösungen:
Die tragbarste Lösung, auch älter
sh
(funktioniert mit Leerzeichen und Glob-Zeichen) (keine Schleife, schneller):Seit Version 2.01 von bash
Für ksh, zsh und bash:
Und für "vorletzte":
Verwenden von printf, um Probleme mit Argumenten zu umgehen, die mit einem Bindestrich beginnen (z
-n
).Für alle Shells und für ältere
sh
(funktioniert mit Leerzeichen und Glob-Zeichen) gilt:Oder wenn Sie eine Variable festlegen möchten
last
:Und für "vorletzte":
quelle
Wenn Sie Bash> = 3.0 verwenden
quelle
echo ${BASH_ARGV[1]}
ARGV
steht für "Argumentvektor".Für
bash
, dieser Kommentar vorgeschlagen , die sehr elegant:Als Bonus funktioniert dies auch in
zsh
.quelle
Dies verschiebt die Argumente um die Anzahl der Argumente minus 1 und gibt das erste (und einzige) verbleibende Argument zurück, das das letzte sein wird.
Ich habe nur in Bash getestet, aber es sollte auch in Sh und Ksh funktionieren.
quelle
shift $(($# - 1))
- Keine Notwendigkeit für ein externes Dienstprogramm. Funktioniert in Bash, ksh, zsh und dash.$((...))
Syntax.printf '%s\n' "$1"
, um unerwartetes Verhalten vonecho
(z-n
. B. für ) zu vermeiden .Wenn Sie dies zerstörungsfrei tun möchten, besteht eine Möglichkeit darin, alle Argumente an eine Funktion zu übergeben und das letzte zurückzugeben:
Wenn es dich eigentlich nicht interessiert , die anderen Argumente beizubehalten, brauchen Sie sie nicht in einer Funktion, aber es fällt mir schwer, an eine Situation zu denken, in der Sie die anderen Argumente niemals behalten möchten, es sei denn, sie wurden bereits verarbeitet. In diesem Fall würde ich die Methode process / shift / process / shift / ... verwenden, um sie nacheinander zu verarbeiten.
Ich gehe hier davon aus, dass Sie sie behalten möchten, weil Sie die sequentielle Methode nicht befolgt haben . Diese Methode behandelt auch den Fall, dass keine Argumente vorhanden sind und "" zurückgegeben werden. Sie können dieses Verhalten leicht anpassen, indem Sie die auskommentierte
else
Klausel einfügen .quelle
Für tcsh:
Ich bin mir ziemlich sicher, dass dies eine tragbare Lösung wäre, abgesehen von der Aufgabe.
quelle
Ich fand die Antwort von @ AgileZebra (plus den Kommentar von @ starfry) am nützlichsten, aber sie setzt
heads
auf einen Skalar. Ein Array ist wahrscheinlich nützlicher:Beachten Sie, dass dies nur Bash ist.
quelle
echo "${heads[-1]}"
das letzte Element in gedrucktheads
. Oder fehlt mir etwas?Eine Lösung mit
eval
:quelle
!
Solast="${!#}"
würde verwendet die gleiche Ansatz (indirekte Referenz auf $ #) in einer viel sichereren, kompakteren, eingebauten, vernünftigen Weise. Und richtig zitiert.=
.${!#}
, aber nicht allgemein: Anführungszeichen werden weiterhin benötigt, wenn der Inhalt wörtliche Leerzeichen enthält, zlast='two words'
. Nur$()
ist Leerzeichen sicher, unabhängig vom Inhalt.Nachdem ich die obigen Antworten gelesen hatte, schrieb ich ein Q & D-Shell-Skript (sollte mit sh und bash funktionieren), um g ++ auf PGM.cpp auszuführen und ein ausführbares Image-PGM zu erstellen. Es wird davon ausgegangen, dass das letzte Argument in der Befehlszeile der Dateiname ist (.cpp ist optional) und alle anderen Argumente Optionen sind.
quelle
Folgendes wird auf
LAST
das letzte Argument gesetzt, ohne die aktuelle Umgebung zu ändern:Wenn andere Argumente nicht mehr benötigt werden und verschoben werden können, kann dies vereinfacht werden zu:
Aus Gründen der Portabilität:
kann ersetzt werden durch:
$()
Wenn wir auch durch Backquotes ersetzen, erhalten wir:quelle
Jetzt muss ich nur noch Text hinzufügen, da meine Antwort zu kurz war, um sie zu veröffentlichen. Ich muss mehr Text zum Bearbeiten hinzufügen.
quelle
$argv
aber nicht$#argv
-$argv[(count $argv)]
wirkt bei Fisch).Dies ist Teil meiner Kopierfunktion:
Gehen Sie folgendermaßen vor, um sie in Skripten zu verwenden:
Erläuterung (am meisten verschachtelt zuerst):
$(echo '$'"$#")
Gibt zurück,$[nr]
wo[nr]
die Anzahl der Parameter ist. ZB die Saite$123
(nicht erweitert).echo $123
Gibt bei Auswertung den Wert des 123. Parameters zurück.eval
erweitert sich einfach$123
auf den Wert des Parameters, zlast_arg
. Dies wird als Zeichenfolge interpretiert und zurückgegeben.Arbeitet ab Mitte 2015 mit Bash.
quelle
quelle
Versuchen Sie das folgende Skript, um das letzte Argument zu finden
Ausgabe:
Vielen Dank.
quelle
Es gibt einen viel prägnanteren Weg, dies zu tun. Argumente für ein Bash-Skript können in ein Array eingefügt werden, was den Umgang mit den Elementen erheblich vereinfacht. Das folgende Skript gibt immer das letzte Argument aus, das an ein Skript übergeben wurde.
Beispielausgabe
quelle
Parametererweiterung verwenden (übereinstimmenden Anfang löschen):
Es ist auch einfach, alles vorletzt zu bekommen:
quelle
Verwenden Sie den speziellen Parameter, um das letzte Argument des zuletzt verwendeten Befehls zurückzugeben:
In diesem Fall funktioniert es, wenn es im Skript verwendet wird, bevor ein anderer Befehl aufgerufen wurde.
quelle
Einfach benutzen
!$
.quelle