web-dev-qa-db-fra.com

Obtenir le dernier argument passé à un script Shell

$1 est le premier argument.
$@ sont tous.

Comment trouver le dernier argument transmis à un script shell?

248
Thomas

C'est un peu un bidouillage:

for last; do true; done
echo $last

Celui-ci est également assez portable (encore une fois, devrait fonctionner avec bash, ksh et sh) et il ne décale pas les arguments, ce qui pourrait être Nice.

Il utilise le fait que for boucle implicitement sur les arguments si vous ne lui indiquez pas ce qu'il faut faire suivre en boucle, et le fait que les variables de boucle for ne sont pas étendues: elles conservent la dernière valeur à laquelle elles ont été définies.

163
Laurence Gonsalves

Ceci est uniquement Bash:

echo "${@: -1}"
276
Dennis Williamson
$ set quick brown fox jumps

$ echo ${*: -1:1} # last argument
jumps

$ echo ${*: -1} # or simply
jumps

$ echo ${*: -2:1} # next to last
fox

L'espace est nécessaire pour qu'il ne soit pas interprété comme un valeur par défaut .

77
Steven Penny

La réponse la plus simple pour bash 3.0 ou supérieur est

_last=${!#}       # *indirect reference* to the $# variable
# or
_last=$BASH_ARGV  # official built-in (but takes more typing :)

C'est ça.

$ cat lastarg
#!/bin/bash
# echo the last arg given:
_last=${!#}
echo $_last
_last=$BASH_ARGV
echo $_last
for x; do
   echo $x
done

La sortie est:

$ lastarg 1 2 3 4 "5 6 7"
5 6 7
5 6 7
1
2
3
4
5 6 7
73
Kevin Little

Utilisez l'indexation combinée avec la longueur de:

echo ${@:${#@}} 
28
Mark Byers

Ce qui suit fonctionnera pour vous. Le @ est pour tableau d'arguments. : signifie à. $ # est la longueur du tableau d'arguments. Donc, le résultat est le dernier élément:

${@:$#} 

Exemple:

function afunction{
    echo ${@:$#} 
}
afunction -d -o local 50
#Outputs 50
26
Tahsin Turkoz

Trouvé ceci en cherchant à séparer le dernier argument de tous les précédents. Bien que certaines réponses obtiennent le dernier argument, elles ne sont pas d'une grande aide si vous avez également besoin de tous les autres arguments. Cela fonctionne beaucoup mieux:

heads=${@:1:$(($# - 1))}
tail=${@:$#}
22
AgileZebra

Cela fonctionne dans tous les shells compatibles POSIX:

eval last=\${$#}

Source: http://www.faqs.org/faqs/unix-faq/faq/part2/section-12.html

19
poiuz

Voici ma solution:

  • joli portable (tous POSIX sh, bash, ksh, zsh) devrait fonctionner
  • ne décale pas les arguments d'origine (décale une copie).
  • n'utilise pas mal eval
  • ne parcourt pas toute la liste
  • n'utilise pas d'outils externes

Code:

ntharg() {
    shift $1
    printf '%s\n' "$1"
}
LAST_ARG=`ntharg $# "$@"`
11
Michał Šrajer

Si vous utilisez Bash> = 3.0

echo ${BASH_ARGV[0]}
8
dusan

Pour ksh, zsh et bash:

$ set -- The quick brown fox jumps over the lazy dog

$ echo "${@:~0}"
dog

Et pour "l'avant dernier":

$ echo "${@:~1:1}"
lazy

Pour résoudre les problèmes d'arguments commençant par un tiret (comme -n), utilisez:

$ printf '%s\n' "${@:~0}"
dog

Et la manière correcte de traiter les espaces et les caractères globaux dans sh est la suivante:

$ set -- The quick brown fox jumps over the lazy dog "the * last argument"

$ eval echo "\"\${$#}\""
The last * argument

Ou, si vous souhaitez définir une variable last var:

$ eval last=\${$#}; echo "$last"
The last * argument

Et pour "l'avant dernier":

$ eval echo "\"\${$(($#-1))}\""
dog
4
Isaac
shift `expr $# - 1`
echo "$1"

Cela décale les arguments du nombre d'arguments moins 1 et renvoie le premier (et le seul) argument restant, qui sera le dernier.

Je n'ai testé que bash, mais cela devrait fonctionner également avec sh et ksh.

2
Laurence Gonsalves

Si vous voulez le faire de manière non destructive, une solution consiste à transmettre tous les arguments à une fonction et à renvoyer le dernier:

#!/bin/bash

last() {
        if [[ $# -ne 0 ]] ; then
            shift $(expr $# - 1)
            echo "$1"
        #else
            #do something when no arguments
        fi
}

lastvar=$(last "$@")
echo $lastvar
echo "$@"

pax> ./qq.sh 1 2 3 a b
b
1 2 3 a b

Si vous ne tenez pas attention sur la conservation des autres arguments, vous n'en avez pas besoin dans une fonction, mais j'ai du mal à penser à une situation dans laquelle vous ne voudriez jamais conserver les autres arguments à moins que ils ont déjà été traités, auquel cas j'utiliserais la méthode process/shift/process/shift/... pour les traiter séquentiellement.

Je suppose ici que vous voulez les conserver parce que vous n'avez pas suivi la méthode séquentielle. Cette méthode gère également le cas où il n'y a pas d'argument, renvoyant "". Vous pouvez facilement ajuster ce comportement en insérant la clause commentée else.

2
paxdiablo

Pour tcsh:

set X = `echo $* | awk -F " " '{print $NF}'`
somecommand "$X"

Je suis à peu près sûr que ce serait une solution portable, sauf pour la mission.

2
Perfect64

Pour bash, ce commentaire a suggéré le très élégant:

echo "${@:$#}"

En prime, cela fonctionne également dans zsh.

2
Tom Hale

Ce qui suit va définir LAST sur le dernier argument sans changer l'environnement actuel:

LAST=$({
   shift $(($#-1))
   echo $1
})
echo $LAST

Si d'autres arguments ne sont plus nécessaires et peuvent être déplacés, vous pouvez le simplifier pour:

shift $(($#-1))
echo $1

Pour des raisons de portabilité suivantes:

shift $(($#-1));

peut être remplacé par:

shift `expr $# - 1`

En remplaçant également $() par des citations arrières, nous obtenons:

LAST=`{
   shift \`expr $# - 1\`
   echo $1
}`
echo $LAST
1
Paweł Nadolski

Une solution utilisant eval:

last=$(eval "echo \$$#")

echo $last
1
Mikael S

Cela fait partie de ma fonction de copie:

eval echo $(echo '$'"$#")

Pour utiliser dans les scripts, procédez comme suit:

a=$(eval echo $(echo '$'"$#"))

Explication (la plus imbriquée en premier):

  1. $(echo '$'"$#") renvoie $[nr][nr] est le nombre de paramètres. Par exemple. la chaîne $123 (non développée).
  2. echo $123 renvoie la valeur du paramètre 123rd, une fois évalué.
  3. eval étend simplement $123 à la valeur du paramètre, par exemple. last_arg. Ceci est interprété comme une chaîne et renvoyé.

Fonctionne avec Bash à partir de mi-2015.

1
Esavier

Après avoir lu les réponses ci-dessus, j’ai écrit un script Q & D Shell (qui devrait fonctionner sous sh et bash) pour exécuter g ++ sur PGM.cpp afin de produire une image exécutable PGM. Il suppose que le dernier argument de la ligne de commande est le nom du fichier (.cpp est facultatif) et que tous les autres arguments sont des options.

#!/bin/sh
if [ $# -lt 1 ]
then
    echo "Usage: `basename $0` [opt] pgm runs g++ to compile pgm[.cpp] into pgm"
    exit 2
fi
OPT=
PGM=
# PGM is the last argument, all others are considered options
for 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 OPT
set -x
g++ -o $DIR/$PGM $OPT $DIR/$PGM.cpp
1
David E.
echo $argv[$#argv]

Maintenant, je dois juste ajouter un texte car ma réponse était trop courte pour être postée. J'ai besoin d'ajouter plus de texte à modifier.

1
frank1rizzo

J'ai trouvé la réponse de @ AgileZebra (plus le commentaire de @ starfry) la plus utile, mais elle définit heads sur un scalaire. Un tableau est probablement plus utile:

heads=( "${@:1:$(($# - 1))}" )
tail=${@:${#@}}
1
EndlosSchleife

Essayez le script ci-dessous pour trouver le dernier argument

 # cat arguments.sh
 #!/bin/bash
 if [ $# -eq 0 ]
 then
 echo "No Arguments supplied"
 else
 echo $* > .ags
 sed -e 's/ /\n/g' .ags | tac | head -n1 > .ga
 echo "Last Argument is: `cat .ga`"
 fi

Sortie:

 # ./arguments.sh
 No Arguments supplied

 # ./arguments.sh testing for the last argument value
 Last Argument is: value

Merci.

0
Ranjithkumar T
#! /bin/sh

next=$1
while [ -n "${next}" ] ; do
  last=$next
  shift
  next=$1
done

echo $last
0
Craig Trader

Il y a une manière beaucoup plus concise de faire ceci. Les arguments d'un script bash peuvent être importés dans un tableau, ce qui simplifie beaucoup la gestion des éléments. Le script ci-dessous imprimera toujours le dernier argument transmis à un script.

  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]}

Échantillon de sortie

$ ./lastarg.sh 1 2 buckle my shoe
shoe
0
tekbot

Utilisation de l’expansion des paramètres (début correspondant à la suppression):

args="$@"
last=${args##* }

Il est également facile d'obtenir tout avant dernier:

prelast=${args% *}
0
Jurij