2009-12-05 69 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

相關問題