bash 相当于 zsh 的 $@[2,$#]

kjo*_*kjo 5 scripting bash zsh shell-script

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

我想知道bash等效的zsh表达式,如$@[2,$#],这直接涉及的范围内的外壳功能的(或脚本的)命令行参数阵列($@)。

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

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

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

% testfn a b c d
>b<
>c<
>d<
Run Code Online (Sandbox Code Playgroud)

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

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

我对不需要中间变量的所有尝试都失败并出现bad substitution错误。

slm*_*slm 5

这对我有用:

testfn () {
   printf '>%s<\n' "${@:2}"
}
Run Code Online (Sandbox Code Playgroud)

例子:

$ testfn a b c d
>b<
>c<
>d<
Run Code Online (Sandbox Code Playgroud)

来自Bash 初学者指南

$@     Expands to the positional parameters, starting from one. When the 
       expansion occurs within double quotes, each parameter expands to a
       separate word.
Run Code Online (Sandbox Code Playgroud)

查看Bash Hacker's Wiki的 Positional Parameters 部分以及Mass Usage部分以获取更多示例和详细信息。

一般当你双引号的形式是$@这样的,"$@"否则"${@:2}"返回的结果会是双引号的结果。

$@可以使用以下表示法访问数组元素 like :

"${@:START:COUNT}"
Run Code Online (Sandbox Code Playgroud)

大量使用部分的摘录

这将从 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<
Run Code Online (Sandbox Code Playgroud)

  • @slm:Stephane Chazelas 所说的是在 zsh 的 `$@[2,$#]` 中,空参数将消失。在 Bash 中和在 zsh 中一样,让空参数消失的唯一方法是让 `$@` 不加引号;但在 Bash 中与 zsh 不同,这将产生其他效果,例如文件名扩展和分词。如果你想禁用这些效果,你必须将 `IFS` 设置为空字符串(禁用分词)并运行 `set -f`(禁用文件名扩展);但是一旦你这样做了,尽管 `$@` 仍然会扩展到所有参数,`${@:2}` 会扩展到一个所有参数连接的字符串。 (3认同)
  • (换句话说,是的:您的 Bash 函数可以工作,并且可能是 OP 想要的,并且 +1。Stephane Chazelas 只是指出 zsh 行为不同的情况,并且正在相当严格地接受 OP 对“等效”的请求.) (2认同)