$1
是第一个参数。
$@
代表所有参数。
如何找到传递给Shell脚本的最后一个参数?
这仅适用于Bash:
echo "${@: -1}"
${@:$#}
只适用于 $@
。 如果你复制 $@
到一个新数组里,例如 arr=("$@")
,${arr[@]:$#}
将会是未定义的。这是因为 $@
有一个零索引元素没有包含在 "$@"
的展开中。 - Mr. Llama$#
的地方是在迭代数组时。因为在Bash中,数组是稀疏的,而$#
会显示数组中的元素数量,但它不一定指向最后一个元素(或元素+1)。换句话说,不能做 for ((i = 0; i++; i < $#)); do something "${array[$i]}"; done
,而应该这样做:for element in "${array[@]}"; do something "$element"; done
,或者迭代索引:for index in "${!array[@]}"; do something "$index" "${array[$index]}"; done
,如果您需要对索引值进行操作。 - Dennis Williamson这有点像是一种技巧:
for last; do true; done
echo $last
这个方法也非常便携(同样适用于bash、ksh和sh),并且不会移动参数,这可能会很不错。
它利用了for循环默认循环参数的特性,如果你不告诉它要循环什么,它就会循环参数,并且for循环变量没有作用域限制:它们保留了最后设置的值。
$ set quick brown fox jumps
$ echo ${*: -1:1} # last argument
jumps
$ echo ${*: -1} # or simply
jumps
$ echo ${*: -2:1} # next to last
fox
添加空格是为了避免其被解释为默认值。
请注意这仅适用于bash。
${@: 1:$#-1}
。 - Dyno Fuecho ${@: -1} ${@: 1:$#-1}
,其中最后一个变成了第一个,其余依次向下滑动。 - Mike对于 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
$BASH_ARGV
在bash函数内部不起作用(除非我做错了什么)。 - Big McLargeHugeBASH_ARGV
将为您提供的是最后一个参数的值,而不仅仅是“最后一个值”。例如:如果您提供了一个单一的参数,然后调用shift,${@:$#}
将不会产生任何结果(因为您已经移除了唯一的参数!),但是,BASH_ARGV
仍将为您提供该(以前的)最后一个参数。 - Steven Lush XXX.sh 1 2 3
执行脚本时,${!#}
不会得到任何东西。 - roamer/bin/bash
)。你在 POSIX sh (/bin/sh
) 中运行它,在许多系统上这不是 bash。 - Adam Katz${@:$#}
例子:
function afunction{
echo ${@:$#}
}
afunction -d -o local 50
#Outputs 50
请注意,这只适用于Bash。
使用索引和长度组合:
echo ${@:${#@}}
请注意,这仅适用于Bash。
在试图将最后一个参数与之前的所有参数分离时,发现了这个问题。虽然有些答案确实可以得到最后一个参数,但如果您需要所有其他参数,它们并没有太大帮助。以下方法效果更好:
heads=${@:1:$#-1}
tail=${@:$#}
请注意,这仅适用于Bash。
${@: -1}
获取最后一个参数,${@: -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}
用于获取倒数第三个参数,以此类推...) - oHo$((...))
来减去1,你可以直接使用${@:1:$#-1}
。 - dkasak这在所有兼容POSIX的shell中都适用:
eval last=\${$#}
来源:http://www.faqs.org/faqs/unix-faq/faq/part2/section-12.html
$#
设置为任意字符串(我不认为会有)。eval last=\"\${$#}\"
也可以工作,并且显然是正确的。不明白为什么不需要引号。 - Paleceval last=\"\${$#}\"
是可以的。但是对于 [tag:csh] 和 [tag:tcsh],请使用 eval set last=\"\${$#}\"
。参考以下示例:tcsh -c 'eval set last=\"\${$#}\"; echo "$last"' arg1 arg2 arg3
。 - oHo这是我的解决方案:
eval
代码:
ntharg() {
shift $1
printf '%s\n' "$1"
}
LAST_ARG=`ntharg $# "$@"`
"$1"
和"$#"
周围添加引号(请参见此优秀答案https://unix.stackexchange.com/a/171347)。其次,`echo`不幸地不可移植(特别是对于`-n`),因此应改用`printf '%s\n' "$1"`。 - jokiecho -n
,但是我不知道任何一个POSIX系统会在echo "$1"
失败。无论如何,printf
确实更可预测-已更新。 - Michał Šrajerlast() { shift $(($# - 1));printf %s "$1";}
- Léa Gris从最古老到较新的解决方案:
最便携的解决方案,甚至包括旧版本的 sh (适用于空格和通配符字符)(无循环,更快):
eval printf "'%s\n'" "\"\${$#}\""
自bash 2.01版本以来
$ set -- The quick brown fox jumps over the lazy dog
$ printf '%s\n' "${!#} ${@:(-1)} ${@: -1} ${@:~0} ${!#}"
dog dog dog dog dog
对于ksh、zsh和bash:
$ printf '%s\n' "${@: -1} ${@:~0}" # the space beetwen `:`
# and `-1` is a must.
dog dog
而对于“倒数第二个”:
$ printf '%s\n' "${@:~1:1}"
lazy
使用printf来解决任何以破折号(如-n
)开头的参数问题。
对于所有类型的shell和旧版的sh
(适用于包含空格和通配符的情况),可采用以下方法:
$ set -- The quick brown fox jumps over the lazy dog "the * last argument"
$ eval printf "'%s\n'" "\"\${$#}\""
The last * argument
或者,如果您想设置一个last
变量:
$ eval last=\${$#}; printf '%s\n' "$last"
The last * argument
而对于“倒数第二个”:
$ eval printf "'%s\n'" "\"\${$(($#-1))}\""
dog
${!#}
。 可以使用bash -c 'echo ${!#}' arg1 arg2 arg3
进行测试。 对于 [tag:bash],[tag:ksh] 和 [tag:zsh],Dennis Williamson 的答案 提出了${@: -1}
。此外${*: -1}
也可以使用。 可以使用zsh -c 'echo ${*: -1}' arg1 arg2 arg3
进行测试。 但是这对于 [tag:dash],[tag:csh] 和 [tag:tcsh] 不起作用。 - oHo${!#}
和${@: -1}
不同,它也可以与参数扩展一起使用。您可以使用bash -c 'echo ${!#%.*}' arg1.out arg2.out arg3.out
进行测试。 - Arch Stanton${!#}
在zsh
中不起作用。对于在{ba,z}sh中都有效的解决方案,请参见此处。 - Tom Hale