如何获取/bin/sh 函数的最后一个参数

kjo*_*kjo 13 shell-script

什么是更好的实施方式print_last_arg

#!/bin/sh

print_last_arg () {
    eval "echo \${$#}"  # this hurts
}

print_last_arg foo bar baz
# baz
Run Code Online (Sandbox Code Playgroud)

(如果这是,#!/usr/bin/zsh而不是#!/bin/sh我知道该怎么做。我的问题是找到一种合理的方法来实现这一点#!/bin/sh。)

编辑:以上只是一个愚蠢的例子。我的目标不是打印最后一个参数,而是有一种方法来引用 shell 函数中的最后一个参数。


EDIT2:对于这样一个措辞不清的问题,我深表歉意。 我希望这次能做对。

如果这是/bin/zsh而不是/bin/sh,我可以写这样的东西

#!/bin/zsh

print_last_arg () {
    local last_arg=$argv[$#]
    echo $last_arg
}
Run Code Online (Sandbox Code Playgroud)

该表达式$argv[$#]是我在第一次编辑中作为引用 shell 函数中最后一个参数的一种方式所描述的示例。

因此,我真的应该像这样编写我的原始示例:

print_last_arg () {
    local last_arg=$(eval "echo \${$#}")   # but this hurts even more
    echo $last_arg
}
Run Code Online (Sandbox Code Playgroud)

...明确表示我所追求的东西放在作业的右边是一件不那么糟糕的事情。

但是请注意,在所有示例中,最后一个参数都是非破坏性访问。IOW,访问最后一个参数使位置参数作为一个整体不受影响。

mik*_*erv 1

eval printf %s${1+"'\n' \"the last arg is \${$#"\}\"}
Run Code Online (Sandbox Code Playgroud)

...如果至少有 1 个参数,则将打印the last arg is后跟<space>、最后一个参数的值和尾随<newline>的字符串,否则,对于零个参数,它将什么也不打印。

如果你这样做:

eval ${1+"lastarg=\${$#"\}}
Run Code Online (Sandbox Code Playgroud)

...然后,如果至少有 1 个参数,则要么将最后一个参数的值分配给 shell 变量,$lastarg要么什么都不做。不管怎样,你都会安全地完成它,而且我认为它甚至应该可以移植到 Olde Bourne shell。

这是另一个类似的方法,尽管它确实需要将整个 arg 数组复制两次(并且需要Bourne shell 的printfin$PATH ) :

if   [ "${1+:}" ]
then set "$#" "$@" "$@"
     shift    "$1"
     printf %s\\n "$1"
     shift
fi
Run Code Online (Sandbox Code Playgroud)

  • 仅供参考,如果不存在参数,您的第一个建议将在旧版 bourne shell 下失败,并出现“错误替换”错误。剩下的两个都按预期工作。 (2认同)