将最后一个参数传递给shell脚本

Tho*_*mas 260 shell arguments

$1是第一个论点.
$@就是他们所有人.

如何找到传递给shell脚本的最后一个参数?

Pau*_*ce. 283

这只是Bash:

echo "${@: -1}"
Run Code Online (Sandbox Code Playgroud)

  • 对于那些(像我一样)想知道为什么需要这个空间,man bash有这样的说法:>注意,负偏移量必须与冒号分开至少一个空格,以避免与: - 扩展混淆. (37认同)
  • **注意:** 这个答案适用于 _all_ Bash 数组,不像 `${@:$#}` 只适用于 `$@`。如果你用 `arr=("$@")` 将 `$@` 复制到一个新数组,`${arr[@]:$#}` 将是未定义的。这是因为 `$@` 有一个第 0 个元素没有包含在 `"$@"` 扩展中。 (3认同)

Lau*_*ves 169

这有点像黑客:

for last; do true; done
echo $last
Run Code Online (Sandbox Code Playgroud)

这个也很可移植(再次,应该使用bash,ksh和sh)并且它不会移动参数,这可能很好.

for如果你不告诉它要循环的内容,它使用隐式循环遍历参数的事实,以及for循环变量没有作用域的事实:它们保留它们设置的最后一个值.

  • @MichałŠrajer,我认为你的意思是冒号而不是逗号;) (10认同)
  • @mcoolive @LaurenceGolsalves旁边更便携,`for last in"$ @"; 做:; 完成`也使意图更加清晰. (7认同)
  • 使用旧的Solaris,使用旧的bourne shell(不是POSIX),我必须写"for last in"$ @"; do true; done" (4认同)
  • ":"而不是真也有效 (4认同)
  • @MichałŠrajer[`true`是POSIX的一部分](http://pubs.opengroup.org/onlinepubs/009695399/utilities/true.html). (2认同)
  • @mcoolive:它甚至可以在 1979 年的 unix v7 bourne shell 中工作。如果它同时在 v7 sh 和 POSIX sh 上运行,你就无法获得更多的可移植性:) (2认同)

小智 78

$ set quick brown fox jumps

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

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

$ echo ${*: -2:1} # next to last
fox
Run Code Online (Sandbox Code Playgroud)

该空间是必要的,因此它不会被解释为默认值.

  • 最佳答案,因为它还包括最后一个arg.谢谢! (7认同)
  • 是。简直是最好的。除了命令和最后一个参数以外的所有变量$``@@:1:$#-1}` (4认同)
  • 史蒂文,我不知道你做了什么才能进入罚球区,但我很喜欢你在这里的工作。 (2认同)

Kev*_*tle 73

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

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

而已.

$ cat lastarg
#!/bin/bash
# echo the last arg given:
_last=${!#}
echo $_last
_last=$BASH_ARGV
echo $_last
for x; do
   echo $x
done
Run Code Online (Sandbox Code Playgroud)

输出是:

$ lastarg 1 2 3 4 "5 6 7"
5 6 7
5 6 7
1
2
3
4
5 6 7
Run Code Online (Sandbox Code Playgroud)

  • `$BASH_ARGV` 在 bash 函数中不起作用(除非我做错了什么)。 (2认同)

Mar*_*ers 29

使用索引结合长度:

echo ${@:${#@}} 
Run Code Online (Sandbox Code Playgroud)

  • 更短:`echo $ {@:$#}` (22认同)
  • 回声 $(@&$;&^$&%@^!@%^#**#&@*#@*#@(&*#_**^@^&(^@&*&@) (3认同)
  • @Atul你能解释一下你有趣的命令吗? (2认同)

Tah*_*koz 28

以下内容适合您.@是参数数组.:意思是.$#是参数数组的长度.结果是最后一个元素:

${@:$#} 
Run Code Online (Sandbox Code Playgroud)

例:

function afunction{
    echo ${@:$#} 
}
afunction -d -o local 50
#Outputs 50
Run Code Online (Sandbox Code Playgroud)


Agi*_*bra 23

在寻找将最后一个参数与前一个参数分开时发现这一点.虽然有些答案确实得到了最后一个论点,但如果你还需要所有其他的args,它们也没什么帮助.这样做效果更好:

heads=${@:1:$(($# - 1))}
tail=${@:$#}
Run Code Online (Sandbox Code Playgroud)

  • [Steven Penny的答案](http://stackoverflow.com/a/11217798/938111)更好一些:使用`$ {@: - 1}`来表示*last*和`$ {@: - 2:1 } for for second last*(依此类推......).示例:`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}`得到*第三个*等等......) (3认同)
  • AgileZebra的答案提供了一种获取*除了最后一个*参数的方法,因此我不会说Steven的答案会取代它。但是,似乎没有理由使用$((...))减去1,您可以简单地使用$$ @@:1:$#-1}。 (2认同)

小智 19

这适用于所有POSIX兼容的shell:

eval last=\${$#}
Run Code Online (Sandbox Code Playgroud)

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

  • 请参阅附加到较旧的相同答案的[此评论](http://stackoverflow.com/questions/1853946/getting-the-last-argument-passed-to-a-shell-script/1854031#comment8318885_1853991)。 (2认同)

Mic*_*jer 11

这是我的解决方案:

  • 非常便携(所有POSIX sh,bash,ksh,zsh)应该可以工作
  • 不会改变原始论点(转移副本).
  • 不使用邪恶 eval
  • 不会遍历整个列表
  • 不使用外部工具

码:

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

  • 这是一个好主意,但我有一些建议:首先应该在`"$1"`和`"$#"`周围添加引号(参见这个很好的答案https://unix.stackexchange.com/a/ 171347)。其次,`echo` 是不可移植的(尤其是对于 `-n`),所以应该使用 `printf '%s\n' "$1"` 代替。 (2认同)
  • 或者: `last() { shift $(($# - 1));printf %s "$1";}` (2认同)

dus*_*san 8

如果您使用的是Bash> = 3.0

echo ${BASH_ARGV[0]}
Run Code Online (Sandbox Code Playgroud)


Lau*_*ves 5

shift `expr $# - 1`
echo "$1"
Run Code Online (Sandbox Code Playgroud)

这会将参数移动参数数量减 1,并返回第一个(也是唯一的)剩余参数,这将是最后一个。

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

  • `shift $(($# - 1))` - 不需要外部实用程序。适用于 Bash、ksh、zsh 和 dash。 (12认同)

Isa*_*aac 5

仅用于bash(自2.01版开始)

$ set -- The quick brown fox jumps over the lazy dog

$ printf '%s\n'     "${!#}     ${@:(-1)} ${@: -1} ${@:~0} ${!#}"
dog     dog dog dog dog
Run Code Online (Sandbox Code Playgroud)

对于ksh,zsh和bash:

$ echo "${@: -1}    ${@:~0}"     # the space beetwen `:` and `-1` is a must.
dog   dog
Run Code Online (Sandbox Code Playgroud)

对于“倒数第二个”:

$ echo "${@:~1:1}"
lazy
Run Code Online (Sandbox Code Playgroud)

要解决以破折号(如-n)开头的参数的任何问题,请使用printf

$ printf '%s\n' "${@:~0}"
dog
Run Code Online (Sandbox Code Playgroud)

对于所有外壳程序和较旧版本sh(适用于空格和glob字符):

$ set -- The quick brown fox jumps over the lazy dog "the * last argument"

$ eval echo "\"\${$#}\""
The last * argument
Run Code Online (Sandbox Code Playgroud)

或者,如果您想设置一个last变量:

$ eval last=\${$#}; echo "$last"
The last * argument
Run Code Online (Sandbox Code Playgroud)

对于“倒数第二个”:

$ eval echo "\"\${$(($#-1))}\""
dog
Run Code Online (Sandbox Code Playgroud)


Tom*_*ale 5

对于bash此注释建议非常优雅:

echo "${@:$#}"
Run Code Online (Sandbox Code Playgroud)

另外,这也适用于zsh