/bin/sh: 提取命令行参数

/bin/sh: extract command line arguments

我正在使用 dash 作为 /bin/sh

我的脚本接受任意数量的参数,我需要这样处理它们,一个变量只包含最后一个参数,另一个变量包含除最后一个参数之外的所有内容。

我知道如何在 zsh 中执行此操作,但不幸的是,这与 dash:

不兼容
last="${@[-1]}"
rest=( ${@[1,-2]} )

我怎样才能在 /bin/sh 中实现这一点?

Posix 标准(破折号实现的)甚至没有数组。

您唯一真正的方法是使用 shift 内置和正常的 arg 访问: 设置 $2 时,$1 不是最后一个参数。当 $2 没有设置时,我们知道 $1 是最后一个参数。现在循环执行此操作并相应地处理参数

像这样的循环(假设至少有一个位置参数):

rest=""
while [ $# != 1 ]; do
    rest="$rest "
    shift
done
last=

您可以简单地旋转现有参数,直到最后一个参数排在最前面,此时您可以将其删除,将剩余的 n-1 个参数留在原来的位置。

n=$#  # Number of arguments

# Rotate the aruguments until the last element is the first
while [ "$n" -gt 1 ]; do
  curr=
  shift
  set -- "$@" "$curr"
  n=$((n-1))
done

lastarg=
shift

# Now $@ is the same as it started, minus its final element.

以上代码适用于 1 个或多个参数。如果没有参数,您可以在处理之前检查它,或者只是等待最终的 shift 失败。 (在后一种情况下,lastarg 将被设置为空字符串,如果真正的最后一个参数确实是空字符串,也会发生这种情况。)