2009-12-05 127 views

回答

135

这是一个黑客位的:

for last; do true; done 
echo $last 

这一个也相当可移植的(同样,应该与bash,ksh和sh一起工作),并且不会改变这些参数d很好。

它使用for隐含地循环参数的事实,如果您不告诉它什么要循环,并且循环变量没有作用域的事实:它们保留它们设置的最后一个值。

+9

@MichałŠrajer,我认为你的意思是冒号而不是逗号;) – 2013-02-26 08:24:01

+1

它适用于我的Android设备。谢谢! – accuya 2013-09-29 19:15:24

+2

@MichałŠrajer['true'是POSIX的一部分](http://pubs.opengroup.org/onlinepubs/009695399/utilities/true.html)。 – Rufflewind 2015-10-09 05:35:35

0
#! /bin/sh 

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

echo $last 
+0

如果参数是空字符串,这将失败,但将在99.9%的情况下工作。 – Thomas 2009-12-06 00:10:20

7

如果使用击> = 3.0

echo ${BASH_ARGV[0]} 
+0

对于接近最后一个参数,执行'echo $ {BASH_ARGV [1]}' – 2012-02-22 02:43:49

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

此通过的参数减1的数目移位的参数,并返回第一个(只)剩余的参数,这将是最后一个。

我只在bash中测试过,但它也应该在sh和ksh中工作。

+7

'shift $(($# - 1))' - 不需要外部工具。在Bash,ksh,zsh和短跑中工作。 – 2010-11-09 02:32:45

+0

@丹尼斯:太棒了!我不知道'$((...))'语法。 – 2010-11-11 16:48:54

+0

为了避免'echo'(例如'-n')出现意外行为,您希望使用'printf'%s \ n'“$ 1”'。 – joki 2018-01-04 09:39:47

2

如果你想要做一个非破坏性的方式,一种方式是将所有参数传递给一个函数,返回最后一个:

#!/bin/bash 

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

lastvar=$(last "[email protected]") 
echo $lastvar 
echo "[email protected]" 

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

如果你实际上并不护理关于保留其他参数,你不需要它在一个函数中,但我很难想到一种情况,你永远不想保留其他参数,除非它们已经被处理,在这种情况下,我会使用按顺序处理它们的过程/移位/过程/移位/ ...方法。

我在这里假设你想保留它们,因为你的还没有遵循顺序方法。这个方法也处理没有参数的情况,返回“”。您可以通过插入注释掉的else子句轻松调整该行为。

26

使用索引与长度相结合:

echo ${@:${#@}} 
+0

只适用于Bash,但一个很好的答案 – 2009-12-06 00:15:24

+0

也适用于ksh。 – 2010-11-09 02:29:04

+18

较短:'echo $ {@:$#}' – 2011-02-28 14:44:32

1

的溶液使用eval

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

echo $last 
+5

对于间接引用的eval是过度杀毒,更不用说不好的做法了,并且存在一个巨大的安全问题(该值不是在echo或$()之外的引用)Bash具有内置语法,用于间接引用,对于任何var:'!'So 'last =“$ {!#}”'会以更安全,紧凑,内在,理智的方式使用相同的方法($#上的间接引用),并且正确引用 – MestreLion 2011-08-07 16:28:28

+0

查看更清晰的方式在[另一个答案](http://stackoverflow.com/a/8868871/2157640) – Palec 2014-10-17 11:23:23

230

这是猛砸只:

echo "${@: -1}" 
+16

也适用于ksh。 – 2010-11-09 02:28:00

+23

也适用于zsh。 – g33kz0r 2011-10-27 06:43:05

+23

对于那些(像我一样)想知道为什么需要这个空间的人,bash有这样的说法: >请注意,一个负偏移量必须与冒号至少分隔一个空格以避免与以下内容混淆: - 扩张。 – foo 2015-05-28 03:34:47

65

对于bash 3.0或更高版本最简单的答案是

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

就是这样。

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

输出是:

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

'$ BASH_ARGV'在bash函数中不起作用(除非我做错了什么)。 – 2014-12-28 15:46:16

19

看向最后一个参数从所有以前的一个(或多个)分开时,发现这一点。 虽然有些答案确实得到了最后一个参数,但如果您还需要所有其他参数,它们也没什么帮助。这个效果要好得多:

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

[Steven Penny的回答](http://stackoverflow.com/a/11217798/938111)更好一些:使用'$ {@:-1}'为* last *和'$ {@:-2: 1}'倒数第二*(等等...)。例如:'bash -c'echo $ {@:-1}'prog 0 1 2 3 4 5 6''打印'6'。要继续使用目前的AgileZebra方法,请使用'$ {@:$# - 1:1}'获取*倒数第二*。例如:'bash -c'echo $ {@:$# - 1:1}'prog 0 1 2 3 4 5 6''打印'5'。 (和'$ {@:$# - 2:1}'得到*倒数*等等......) – olibre 2015-11-26 08:05:53

+0

AgileZebra的答案提供了一种获得*除最后*参数外的所有方法,所以我不会说史蒂文的回答取代它。但是,似乎没有理由使用'$((...))'来减去1,您可以简单地使用'$ {@:1:$# - 1}'。 – dkasak 2016-11-04 20:02:08

16

这适用于所有POSIX兼容的外壳:

eval last=\${$#} 

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

+1

请参阅[此评论](http://stackoverflow.com/questions/1853946/getting-the-last-argument-passed-to-a-shell-script/1854031#comment8318885_1853991)附加到旧的相同的答案。 – 2012-07-13 12:21:28

+1

我在这里看到的最简单的便携式解决方案。这个没有安全问题,@DennisWilliamson,除非有一种方法可以将'$#'设置为一个任意字符串(我不这么认为),否则引用经验似乎是正确的。 'eval last = \“\ $ {$#} \”'也起作用,显然是正确的。不明白为什么不需要引号。 – Palec 2014-10-17 11:47:52

+0

对于[tag:bash],[tag:zsh],[tag:dash]和[tag:ksh]'eval last = \“\ $ {$#} \”'很好。但对于[tag:csh]和[tag:tcsh],使用'eval set last = \“\ $ {$#} \”'。看到这个例子:'tcsh -c'eval set last = \“\ $ {$#} \”; echo“$ last”'arg1 arg2 arg3'。 – olibre 2017-07-22 21:11:20

61
$ set quick brown fox jumps 

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

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

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

的空间是必要的,这样它不得到解释为default value

+5

最佳答案,因为它还包括倒数第二个参数。谢谢! – e40 2013-07-07 00:54:55

+0

史蒂文,我不知道你在罚球箱上的表现如何,但我热爱你在这里的工作。 – 2017-09-22 15:09:01

1

阅读上述我写的Q- & d外壳脚本中的应答后(应在工作sh和bash)的上PGM.cpp运行克++,以产生可执行映像PGM。它假定命令行上的最后一个参数是文件名(.cpp是可选的),并且所有其他参数都是选项。

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

这里是我的解决方案:

  • 漂亮的便携式(所有POSIX SH时,bash和ksh,zsh中)应该工作
  • 不移位原始参数(移动副本)。
  • 不使用 邪恶 eval
  • 不通过整个列表迭代
  • 不使用外部工具

代码:

ntharg() { 
    shift $1 
    printf '%s\n' "$1" 
} 
LAST_ARG=`ntharg $# "[email protected]"` 
+0

很好的答案 - 简短,便携,安全。谢谢! – 2016-10-07 09:45:37

+1

这是一个好主意,但我有几点建议:首先应该在''1“'和''$#'''周围添加引号”(请参阅​​https://unix.stackexchange.com/a/171347)。其次,'echo'可悲的是不可移植的(特别是'-n'),所以应该使用'printf'%s \ n'“$ 1”'来代替。 – joki 2018-01-04 09:37:29

+0

谢谢@joki我与很多不同的unix系统一起工作,我也不信任'echo -n',但是我不知道任何posix系统中echo $ 1“'会失败。无论如何,'printf'确实是更可预测的 - 更新。 – 2018-01-09 14:11:36

1

下面我们来设置LAST持续不改变当前环境的说法:

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

如果不再需要的其他参数和可以移动,可以简化为:

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

对于便携性的原因如下:

shift `expr $# - 1` 

shift $(($#-1)); 

可以替换

更换$()带反引号我们得到:

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

尝试下面的脚本来找到最后一个参数

# 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 

输出:

# ./arguments.sh 
No Arguments supplied 

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

感谢。

+0

我怀疑这会失败./arguments.sh“最后一个值” – Thomas 2013-11-05 03:25:01

+0

谢谢你检查托马斯,我试图执行像你一样的脚本mentinoed#./arguments.sh“last value” Last Argument is:value现在工作正常。 #./arguments.sh“使用双精度值检查” 最后一个参数是:double – 2013-11-05 17:56:27

+0

问题是最后一个参数是'最后一个值',而不是值。错误是由包含空格的参数引起的。 – Thomas 2013-11-08 03:02:18

2

对于tcsh:

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

我确信这将是一个便携式解决方案,除了分配。

+0

我知道你永远发布了这个,但这个解决方案非常棒 - 很高兴有人发布了tcsh! – user3295674 2015-02-26 15:30:26

1
echo $argv[$#argv] 

现在我只需要添加一些文字,因为我的回答太短而无法发布。我需要添加更多文本才能编辑。

+0

这是哪个外壳可以工作?不bash。不是鱼(具有'$ argv',但不是'$#argv' - '$ argv [(count $ argv)]'适用于鱼类)。 – 2014-12-16 16:02:09

+3

啊,这在[t] csh中有效。 – 2014-12-16 16:17:04

-1

有一个更简洁的方法来做到这一点。 bash脚本的参数可以放入一个数组中,这使得处理元素变得更加简单。下面的脚本将始终打印传递给脚本的最后一个参数。

argArray=("[email protected]")      # 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]} 

样本输出

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

我发现@ AgileZebra的回答(加上@ starfry的评论)是最有用的,但它设置heads一个标。数组可能是更有益的:

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

这仅仅是bash – josch 2015-02-15 07:48:39

-1

这可以格式的Slackware和Cygwin工作。

“$ {X [@]:( - 1)}”,如果与$ @, “$ {@:( - 1)}” 中使用

它的意思是:$ {@ :(Ñ )},将返回N索引后的所有元素。(包括N), -1是最后的。

0

这是我的复制功能的一部分:

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

要在脚本中使用,这样做:

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

解释(最嵌套在前):

  1. $(echo '$'"$#")回报$[nr]其中[nr]是参数的数量。例如。字符串$123(未展开)。
  2. echo $123在计算时返回123rd参数的值。
  3. eval只是将$123扩展为参数的值,例如, last_arg。这被解释为一个字符串并返回。

工程与bash作为2015年

+0

eval方法已经在这里多次介绍过了,但是这个方法已经解释了它的工作原理。可以进一步改进,但仍值得保留。 – Palec 2015-08-18 23:17:12

18

下面中旬会为你工作。 @是用于参数数组的。 :意思是。 $#是参数数组的长度。所以结果是最后一个元素:

${@:$#} 

例子:

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

虽然这个例子是针对一个函数的,但脚本的工作方式也是一样的。我喜欢这个答案,因为它很清晰和简洁。 – 2017-10-03 03:43:29

+0

而且这不是哈克。它使用语言的显式特征,而不是副作用或特殊问题。这应该是被接受的答案。 – musicin3d 2018-01-05 16:09:16

相关问题