tutorial script example español ejemplos shell arguments

script - shell sh



Obteniendo el último argumento pasado a un script de shell (26)

Aquí está la solución mía:

  • bastante portátil (todo POSIX sh, bash, ksh, zsh) debería funcionar
  • no desplaza los argumentos originales (desplaza una copia).
  • no usa el mal eval
  • no itera a través de toda la lista
  • no utiliza herramientas externas

Código:

ntharg() { shift $1 printf ''%s/n'' "$1" } LAST_ARG=`ntharg $# "$@"`

$1 es el primer argumento.
$@ son todos ellos.

¿Cómo puedo encontrar el último argumento pasado a un script de shell?


Después de leer las respuestas anteriores, escribí un script de shell Q&D (debería funcionar en sh y bash) para ejecutar g ++ en PGM.cpp para producir una imagen ejecutable PGM. Se supone que el último argumento en la línea de comando es el nombre del archivo (.cpp es opcional) y todos los demás argumentos son opciones.

#!/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


Encontré esto cuando se busca separar el último argumento de todos los anteriores. Si bien algunas de las respuestas obtienen el último argumento, no son de mucha ayuda si también necesita todos los otros argumentos. Esto funciona mucho mejor:

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


Encontré la respuesta de @AgileZebra (más el comentario de @ Starfry) la más útil, pero pone heads a un escalar. Una matriz es probablemente más útil:

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


Este formato puede funcionar en Slackware y Cygwin.

"$ {x [@]: (- 1)}", si se usa con $ @, "$ {@: (- 1)}"

Significa que es: $ {@ :( N)}, devolverá todos los elementos después del índice N. (incluir N), -1 es el último.


Esto es parte de mi función de copia:

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

Para usar en scripts, haga esto:

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

Explicación (la más anidada primero):

  1. $(echo ''$''"$#") devuelve $[nr] donde [nr] es el número de parámetros. Por ejemplo, la cadena $123 (sin dilatar).
  2. echo $123 devuelve el valor del parámetro 123, cuando se evalúa.
  3. eval simplemente expande $123 al valor del parámetro, por ejemplo, last_arg . Esto se interpreta como una cadena y se devuelve.

Trabaja con Bash desde mediados de 2015.


Esto es solo Bash:

echo "${@: -1}"


Esto es un poco de un hack:

for last; do true; done echo $last

Este también es bastante portátil (de nuevo, debería funcionar con bash, ksh y sh) y no cambia los argumentos, lo que podría ser bueno.

Utiliza el hecho de que for los bucles implícitamente sobre los argumentos si no le dices qué bucear, y el hecho de que las variables de bucle no están dentro del alcance: conservan el último valor en el que se establecieron.



Hay una manera mucho más concisa de hacer esto. Los argumentos de una secuencia de comandos bash se pueden incluir en una matriz, lo que simplifica mucho el manejo de los elementos. La siguiente secuencia de comandos siempre imprimirá el último argumento pasado a una secuencia de comandos.

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

Salida de muestra

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


La respuesta más simple para bash 3.0 o superior es

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

Eso es.

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

La salida es:

$ lastarg 1 2 3 4 "5 6 7" 5 6 7 5 6 7 1 2 3 4 5 6 7


Lo siguiente establecerá LAST en el último argumento sin cambiar el entorno actual:

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

Si otros argumentos ya no son necesarios y se pueden cambiar, se puede simplificar para:

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

Por razones de portabilidad siguientes:

shift $(($#-1));

puede ser reemplazado con:

shift `expr $# - 1`

Reemplazando también $() con backquotes obtenemos:

LAST=`{ shift /`expr $# - 1/` echo $1 }` echo $LAST


Lo siguiente funcionará para usted. La @ es para la matriz de argumentos. : significa en. $ # es la longitud de la matriz de argumentos. Entonces el resultado es el último elemento:

${@:$#}

Ejemplo:

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



Para ksh, zsh y bash:

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

Y para "next to last":

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

Para solucionar cualquier problema con los argumentos que comienzan con un guión (como -n ) use:

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

Y la forma correcta de tratar con espacios y caracteres globales en sh es:

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

O bien, si desea establecer una last var:

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

Y para "next to last":

$ eval echo "/"/${$(($#-1))}/"" dog


Para tcsh:

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

Estoy bastante seguro de que esta sería una solución portátil, a excepción de la asignación.


Pruebe el siguiente script para encontrar el último argumento

# 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

Salida:

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

Gracias.


Si está utilizando Bash> = 3.0

echo ${BASH_ARGV[0]}


Si quieres hacerlo de una manera no destructiva, una forma es pasar todos los argumentos a una función y devolver el último:

#!/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 realmente no te importa mantener los otros argumentos, no lo necesitas en una función, pero me cuesta pensar en una situación en la que nunca querrías mantener los otros argumentos a menos que ya hayan sido procesados. en cuyo caso utilizaría el método process / shift / process / shift / ... para procesarlos secuencialmente.

Supongo que aquí desea conservarlas porque no ha seguido el método secuencial. Este método también maneja el caso donde no hay argumentos, devolviendo "". Puede ajustar fácilmente ese comportamiento insertando la cláusula else comentada.


Una solución utilizando eval :

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


Usando la expansión de parámetros (eliminar el inicio coincidente):

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

También es fácil conseguir todo antes de lo último:

prelast=${args% *}


Utilice la indexación combinada con la longitud de:

echo ${@:${#@}}


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


$ set quick brown fox jumps $ echo ${*: -1:1} # last argument jumps $ echo ${*: -1} # or simply jumps $ echo ${*: -2:1} # next to last fox

El espacio es necesario para que no se interprete como un valor predeterminado .


echo $argv[$#argv]

Ahora solo necesito agregar un poco de texto porque mi respuesta fue demasiado corta para publicar. Necesito añadir más texto para editar.


shift `expr $# - 1` echo "$1"

Esto desplaza los argumentos por el número de argumentos menos 1, y devuelve el primer (y único) argumento restante, que será el último.

Solo probé en bash, pero también debería funcionar en sh y ksh.