Getting the last argument passed to a shell script

匿名 (未验证) 提交于 2019-12-03 02:11:02

问题:

$1 is the first argument.
$@ is all of them.

How can I find the last argument passed to a shell script?

回答1:

This is a bit of a hack:

for last; do true; done echo $last 

This one is also pretty portable (again, should work with bash, ksh and sh) and it doesn't shift the arguments, which could be nice.

It uses the fact that for implicitly loops over the arguments if you don't tell it what to loop over, and the fact that for loop variables aren't scoped: they keep the last value they were set to.



回答2:

This is Bash-only:

echo "${@: -1}" 


回答3:

The simplest answer for bash 3.0 or greater is

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

That's it.

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

Output is:

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


回答4:

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

The space is necessary so that it doesnt get interpreted as a default value.



回答5:

Use indexing combined with length of:

echo ${@:${#@}}  


回答6:

The following will work for you. The @ is for array of arguments. : means at. $# is the length of the array of arguments. So the result is the last element:

${@:$#}  

Example:

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


回答7:

Found this when looking to separate the last argument from all the previous one(s). Whilst some of the answers do get the last argument, they're not much help if you need all the other args as well. This works much better:

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


回答8:

This works in all POSIX-compatible shells:

eval last=\${$#} 

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



回答9:

If you are using Bash >= 3.0

echo ${BASH_ARGV[0]} 


回答10:

Here is mine solution:

  • pretty portable (all POSIX sh, bash, ksh, zsh) should work
  • does not shift original arguments (shifts a copy).
  • does not use evil eval
  • does not iterate through the whole list
  • does not use external tools

Code:

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


回答11:

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

This shifts the arguments by the number of arguments minus 1, and returns the first (and only) remaining argument, which will be the last one.

I only tested in bash, but it should work in sh and ksh as well.



回答12:

If you want to do it in a non-destructive way, one way is to pass all the arguments to a function and return the last one:

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

If you don't actually care about keeping the other arguments, you don't need it in a function but I have a hard time thinking of a situation where you would never want to keep the other arguments unless they've already been processed, in which case I'd use the process/shift/process/shift/... method of sequentially processing them.

I'm assuming here that you want to keep them because you haven't followed the sequential method. This method also handles the case where there's no arguments, returning "". You could easily adjust that behavior by inserting the commented-out else clause.



回答13:

For tcsh:

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

I'm quite sure this would be a portable solution, except for the assignment.



回答14:

A solution using eval:

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


回答15:

After reading the answers above I wrote a Q&D shell script (should work on sh and bash) to run g++ on PGM.cpp to produce executable image PGM. It assumes that the last argument on the command line is the file name (.cpp is optional) and all other arguments are 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 


回答16:

The following will set LAST to last argument without changing current environment:

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

If other arguments are no longer needed and can be shifted it can be simplified to:

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

For portability reasons following:

shift $(($#-1)); 

can be replaced with:

shift `expr $# - 1` 

Replacing also $() with backquotes we get:

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


回答17:

echo $argv[$#argv] 

Now I just need to add some text because my answer was too short to post. I need to add more text to edit.



回答18:

I found @AgileZebra's answer (plus @starfry's comment) the most useful, but it sets heads to a scalar. An array is probably more useful:

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


回答19:

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


回答20:

This is part of my copy function:

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

To use in scripts, do this:

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

Explanation (most nested first):

  1. $(echo '$'"$#") returns $[nr] where [nr] is the number of parameters. E.g. the string $123 (unexpanded).
  2. echo $123 returns the value of 123rd parameter, when evaluated.
  3. eval just expands $123 to the value of the parameter, e.g. last_arg. This is interpreted as a string and returned.

Works with Bash as of mid 2015.



回答21:

Try the below script to find last 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 

Output:

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

Thanks.



回答22:

There is a much more concise way to do this. Arguments to a bash script can be brought into an array, which makes dealing with the elements much simpler. The script below will always print the last argument passed to a 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]} 

Sample output

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


回答23:

This format can worked in Slackware and Cygwin.

"${x[@]:(-1)}", if used with $@, "${@:(-1)}"

It means is: ${@:(N)}, will return all element after N index.(include N), -1 is thelast.



回答24:

Using parameter expansion (delete matched beginning):

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

It's also easy to get all before last:

prelast=${args% *} 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!