有什么更好的实施方法print_last_arg
?
#!/bin/sh
print_last_arg () {
eval "echo \${$#}" # this hurts
}
print_last_arg foo bar baz
# baz
(如果是这样的话,我#!/usr/bin/zsh
就会#!/bin/sh
知道该怎么做。我的问题是找到一种合理的方法来实现这一点#!/bin/sh
。)
编辑:上面只是一个愚蠢的例子。我的目标不是打印最后一个参数,而是有一种方法来引用 shell 函数中的最后一个参数。
编辑2:对于这样一个措辞不明确的问题,我深表歉意。 我希望这次能做对。
如果这是/bin/zsh
代替的话/bin/sh
,我可以写这样的东西
#!/bin/zsh
print_last_arg () {
local last_arg=$argv[$#]
echo $last_arg
}
表达方式$argv[$#]
是我在第一次编辑中描述的示例一种在 shell 函数中引用最后一个参数的方法。
因此,我真的应该这样写我原来的例子:
print_last_arg () {
local last_arg=$(eval "echo \${$#}") # but this hurts even more
echo $last_arg
}
...为了明确我所追求的是放在作业右侧的不那么可怕的东西。
但请注意,在所有示例中,都会访问最后一个参数非破坏性地。 IOW,访问最后一个参数不会影响整个位置参数。
答案1
给出开篇文章的示例(不带空格的位置参数):
print_last_arg foo bar baz
对于默认的IFS=' \t\n'
,怎么样:
args="$*" && printf '%s\n' "${args##* }"
为了更安全地扩展"$*"
,请设置 IFS (根据@StéphaneChazelas):
( IFS=' ' args="$*" && printf '%s\n' "${args##* }" )
但是如果你的位置参数可以包含空格,上面的方法将会失败。在这种情况下,请改用:
for a in "$@"; do : ; done && printf '%s\n' "$a"
请注意,这些技术避免使用eval
并且没有副作用。
答案2
答案3
这是一个简单的方法:
print_last_arg () {
if [ "$#" -gt 0 ]
then
s=$(( $# - 1 ))
else
s=0
fi
shift "$s"
echo "$1"
}
(根据 @cuonglm 的观点进行更新,即原始版本在不传递任何参数时失败;这现在回显空行 -else
如果需要,请更改子句中的行为)
答案4
这应该适用于任何符合 POSIX 标准的 shell,也适用于 POSIX 之前的遗留 Solaris Bourne shell:
do=;for do do :;done;printf "%s\n" "$do"
这是一个基于相同方法的函数:
print_last_arg()
if [ "$*" ]; then
for do do :;done
printf "%s\n" "$do"
else
echo
fi
PS:别告诉我我忘记了函数体周围的大括号;-)