bash 相当于 zsh 的 $@

bash 相当于 zsh 的 $@

(注意:这个问题的动机只是为了提高我的bash编程知识。)

我想知道bash等价zsh于 的表达式$@[2,$#]直接地寻址 shell 函数(或脚本)的命令行参数数组 ( $@) 的范围。

(我在网上找到的所有解决范围的解决方案$@bash可以描述为“间接寻址”,因为它们都需要首先分配$@给中间变量。请参见下面的示例。)

为了具体起见:bash以下zsh测试函数的等价物是什么?

testfn () {
  printf '>%s<\n' $@[2,$#]
}

% testfn a b c d
>b<
>c<
>d<

以下是我设法想出的最接近的;如上所述,它需要将 赋值$@给中间变量:

testfn () {
  holdargs=( $@ )
  printf '>%s<\n' "${holdargs[@]:1}"
}

我对不需要中间变量的所有尝试都因错误而失败bad substitution

答案1

这对我有用:

testfn () {
   printf '>%s<\n' "${@:2}"
}

例子:

$ testfn a b c d
>b<
>c<
>d<

Bash b 初学者指南

$@     Expands to the positional parameters, starting from one. When the 
       expansion occurs within double quotes, each parameter expands to a
       separate word.

查看位置参数部分Bash 黑客维基以及大量使用部分了解更多示例和详细信息。

一般情况下当你用双引号形式的时候是$@这样的,"$@"否则"${@:2}"返回的结果将是双引号结果。

$@可以使用以下符号访问数组元素:

"${@:START:COUNT}"

摘自“大量使用”部分

这将从 START 开始扩展 COUNT 个位置参数。 COUNT 可以省略 (${@:START}),在这种情况下,从 START 开始的所有位置参数都会展开。

空元素?

其他人指出上面的内容并不等效,因为它无法处理空元素。我使用的是 Bash 4.1.7,看起来确实如此。

例子:

$ testfn "" a "" c d e
>a<
><
>c<
>d<
>e<

$ testfn '' a '*' c d e
>a<
>*<
>c<
>d<
>e<

$ testfn "" a " " c d e
>a<
> <
>c<
>d<
>e<

答案2

zsh

printf '<%s>\n' ${@[2,$#]}

与...一样

printf '<%s>\n' $@[2,-1]

打印非空位置元素 2 到最后一个。这与编写相同(如果 $# == 5):

printf '<%s>\n' $2 $3 $4 $5

所以:

$ set 1 2 '' '*' 5
$ printf '<%s>\n' $@[2,-1]
<2>
<*>
<5>

要获得 中的等价物bash,您需要:

$ set 1 2 '' '*' 5
$ a=("$@")
$ IFS=; set -f
$ printf '<%s>\n' ${a[@]:1}
<2>
<*>
<5>

您需要一个中间数组,因为${@:2}这样不行(至少在 4.2.45 中不行)。

当然,如果您想要除第一个元素之外的所有元素,无论它们是否为空,您都必须编写它:

$ printf '<%s>\n' "$@[2,-1]"
<2>
<>
<*>
<5>

zsh

$ printf '<%s>\n' "${@:2}"
<2>
<>
<*>
<5>

bash

请注意,zsh最终包含了${array:first:n}语法(仅当它不与 csh 样式修饰符冲突时),因此上面的 bash(实际上是 ksh)代码也可以在较新版本的zsh.

${a[@]:1}至于与 之间差异的原因${@:2},您必须记住,在 中,与or或bash相反,但与复制其数组的位置一样,数组是稀疏的并且索引从 0 开始。zshcshrckshbash

${a[@]:4:5}返回索引大于或等于 4 的前 5 个元素。 第一个元素的$@索引为 1 ( $1),而定义为 的数组a=(...)其元素设置为索引从 0 开始。

嗯,这并不完全正确。在bash,中,"$@"像 一样扩展"$1" "$2" "$3" "$4" "$5",而当且仅当 $# > 0 时,"${@:0:1}"就像while (不带引号)一样,只有在未设置或非空时才像。这对我来说听起来像是错误。中的行为有所不同,但再次保持一致。"$0""$@""${@:1}"$@${@:1}$IFSksh

相关内容