$@ 除了第一个参数

$@ 除了第一个参数

我需要编写一个以这种方式运行的 shell 脚本:

./myscript arg1 arg2_1 arg2_2 arg2_3 ....... arg2_#

脚本中有一个 for 循环

for i in $@

然而,据我所知,$@ 包括 $1 到 $($#-1)。但对于我的程序来说,$1 与 $2 $3 $4 等明显不同。我想从 $2 循环到最后...我该如何实现这一点?谢谢你:)

答案1

首先,请注意,$@不带引号是没有意义的,不应使用。$@只能在引用 ( "$@") 和列表上下文中使用。

for i in "$@"符合列表上下文的条件,但在这里,为了循环位置参数,规范的、最可移植且最简单的形式是:

for i
do something with "$i"
done

现在,要从第二个元素开始循环遍历元素,规范且最便携的方法是使用shift

first_arg=$1
shift # short for shift 1
for i
do something with "$i"
done

之后shift,原来的内容$1已从列表中删除(但我们已将其保存在 中$first_arg),而原来的内容$2现在位于$1。位置参数为转移 1位置向左(用于shift 2移动 2...)。所以基本上,我们的循环是从以前的第二个参数循环到最后一个参数。

使用bash(和zshksh93,但就是这样),另一种方法是执行以下操作:

for i in "${@:2}"
do something with "$i"
done

但请注意,它不是标准sh语法,因此不应在以#! /bin/sh -.

zsh或中yash,您还可以执行以下操作:

for i in "${@[3,-3]}"
do something with "$i"
done

从第三个参数循环到第三个最后一个参数。

在 中zsh$@也称为$argv数组。因此,要从数组的开头或结尾弹出元素,您还可以执行以下操作:

argv[1,3]=() # remove the first 3 elements
argv[-3,-1]=()

shift也可以1=()写成zsh

在 中bash,您只能使用内置元素分配给元素$@set因此要从末尾弹出 3 个元素,类似于:

set -- "${@:1:$#-3}"

并从第三个循环到最后第三个:

for i in "${@:3:$#-5}"
do something with "$i"
done

POSIXly,要弹出 的最后 3 个元素"$@",您需要使用循环:

n=$(($# - 3))
for arg do
  [ "$n" -gt 0 ] && set -- "$@" "$arg"
  shift
  n=$((n - 1))
done

答案2

我想你想要shift内置的。它重命名$2$1$3to$2等。

像这样:

shift
for i in "$@"; do
    echo $i
done

答案3

总是有穴居人的方法:

first=1
for i
do
        if [ "$first" ]
        then
                first=
                continue
        fi
        something with "$i"
done

这会$@保持完整(以防您以后想使用它),并且简单地循环每个参数,但不处理第一个参数。

答案4

在 bash 中,您还可以使用显式索引编写该循环:

for ((i=2; i<=$#; ++i)); do
  process "${!i}"
done

这会迭代从第二个到最后一个的所有参数。如果您想排除最后一个参数,只需这样做

for ((i=1; i<=$#-1; ++i)); do
  process "${!i}"
done

如果您只想采用所有其他参数,请将其写为

for ((i=1; i<=$#; i+=2)); do
  process "${!i}"
done

这背后的故事是算术的版本for内置,结合参数计数$#变量间接${…}

一个很好的应用是,您可以使用它来在循环内决定给定选项是否将其后面的参数作为值。如果是,则增加i(例如写入: $((++i)))以消耗下一个值并在迭代期间跳过它。

相关内容