Passer le dernier argument à un script shell

$1 est le premier argument.
$@ est tout.

Comment trouver le dernier argument transmis à un script shell?

    C’est un peu un hack:

     for last; do true; done echo $last 

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

    Il utilise le fait que for boucles implicitement sur les arguments si vous ne lui dites pas ce qu’il faut parcourir, et le fait que pour les variables de boucle ne sont pas définis: ils conservent la dernière valeur à laquelle ils ont été définis.

    Ceci est Bash-only:

     echo "${@: -1}" 

    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 tout.

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

    Le résultat est:

     $ lastarg 1 2 3 4 "5 6 7" 5 6 7 5 6 7 1 2 3 4 5 6 7 
     $ 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 une valeur par défaut .

    Utiliser l’indexation combinée avec la longueur de:

     echo ${@:${#@}} 

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

     ${@:$#} 

    Exemple:

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

    Vous l’avez trouvé en cherchant à séparer le dernier argument de tous les précédents. Bien que certaines des réponses obtiennent le dernier argument, elles ne sont pas très utiles si vous avez également besoin de tous les arguments. Cela fonctionne beaucoup mieux:

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

    Cela fonctionne dans tous les shells compatibles POSIX:

     eval last=\${$#} 

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

    Si vous utilisez Bash> = 3.0

     echo ${BASH_ARGV[0]} 

    Voici la solution:

    • assez portable (tout POSIX sh, bash, ksh, zsh) devrait fonctionner
    • ne décale pas les arguments originaux (décale une copie).
    • n’utilise pas mal eval
    • ne pas parcourir toute la liste
    • n’utilise pas d’outils externes

    Code:

     ntharg() { shift $1 printf '%s\n' "$1" } LAST_ARG=`ntharg $# "$@"` 
     shift `expr $# - 1` echo "$1" 

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

    J’ai seulement testé en bash, mais ça devrait fonctionner aussi bien en sh qu’en ksh.

    Si vous voulez le faire de manière non destructive, vous pouvez passer 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 ab b 1 2 3 ab 

    Si vous ne vous souciez pas vraiment de conserver les autres arguments, vous n’en avez pas besoin dans une fonction, mais j’ai du mal à penser à une situation où vous ne voudriez jamais conserver les autres arguments à moins qu’ils aient déjà été traités. Dans ce cas, j’utiliserais la méthode process / shift / process / shift / … pour les traiter séquentiellement.

    Je suppose que vous voulez les conserver car 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’arguments, en retournant “”. Vous pouvez facilement ajuster ce comportement en insérant la clause else commentée.

    Pour tcsh:

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

    Je suis sûr que ce serait une solution portable, à l’exception de la mission.

    Une solution utilisant eval :

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

    Après avoir lu les réponses ci-dessus, j’ai écrit un script shell Q & D (devrait fonctionner sur sh et bash) pour exécuter g ++ sur PGM.cpp afin de produire une image PGM exécutable. 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 comstack 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 

    Ce qui suit définit le dernier argument sans modifier 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, il peut être simplifié pour:

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

    Pour des raisons de portabilité suivantes:

     shift $(($#-1)); 

    peut être remplacé par:

     shift `expr $# - 1` 

    En remplaçant aussi $() par des backquotes, nous obtenons:

     LAST=`{ shift \`expr $# - 1\` echo $1 }` echo $LAST 
     echo $argv[$#argv] 

    Maintenant, j’ai juste besoin d’append du texte car ma réponse était trop courte pour poster. Je dois append plus de texte à modifier.

    J’ai trouvé la réponse de @AgileZebra (le commentaire de plus @ starfry) la plus utile, mais elle place les heads dans un scalaire. Un tableau est probablement plus utile:

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

    Pour ksh, zsh et bash:

     $ set -- The quick brown fox jumps over the lazy dog $ echo "${@:~0}" dog 

    Et pour “next to last”:

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

    Pour contourner tous les problèmes avec des 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:

     $ set -- The quick brown fox jumps over the lazy dog "the * last argument" $ eval echo "\"\${$#}\"" The last * argument 

    Ou, si vous voulez définir un last var:

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

    Et pour “next to last”:

     $ eval echo "\"\${$(($#-1))}\"" dog 
     #! /bin/sh next=$1 while [ -n "${next}" ] ; do last=$next shift next=$1 done echo $last 

    Ceci fait partie de ma fonction de copie:

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

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

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

    Explication (le plus nested en premier):

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

    Fonctionne avec Bash dès la mi-2015.

    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.

    Il existe un moyen beaucoup plus concis de le faire. Les arguments pour un script bash peuvent être placés dans un tableau, ce qui simplifie 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]} 

    Sortie de l’échantillon

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

    Ce format peut fonctionner dans Slackware et Cygwin.

    “$ {x [@]: (- 1)}”, si utilisé avec $ @, “$ {@: (- 1)}”

    Cela signifie que: $ {@ 🙁 N)}, renverra tous les éléments après l’index N. (inclure N), -1 est le dernier.

    Utilisation de l’extension de paramètre (supprimer le début correspondant):

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

    Il est également facile de tout obtenir avant la fin:

     prelast=${args% *}