zsh:从函数返回关联数组

4
如何从zsh函数返回关联数组?
我尝试过:
creatAARR() {
    declare -A AARR=([k1]=2 [k2]=4)
    return $AARR
}
creatAARR

但是我遇到了错误:

creatAARR:return:2: too many arguments

什么是正确的方法?

编辑: 我按照 @chepner 的建议将输出捕获到标准输出中,但新变量似乎并不像关联数组一样运行:

creatAARR() {
    declare -A AARR=([k1]=2 [k2]=4)
    echo "$AARR"
}
declare -A VALL
NEW_ARR=$(creatAARR)
echo "$NEW_ARR" # 2 4
echo "k1: $NEW_ARR[k1]" # prints just k1:
return

有什么建议吗?


1
你不能这样做。Shell函数不返回数据,它们返回表示成功或失败的整数状态码。你可以设置一个全局变量,或者将数据写入标准输出,让调用者使用$(...)来捕获。 - chepner
想要做到那一点是你需要使用更强大的语言的一个重要提示。当 shell 无法胜任时,我喜欢使用 Perl 和 TCL,有些人则非常喜欢 Python... - Shawn
@chepner已经回答了,但是分配的变量不是一个关联数组。问题已更新。 - Alterecho
1
echo "$NEW_ARR" 不会写入数组值(在 shell 中不存在这样的东西;数组语法基本上是一种使用类似名称的多个变量的方式);它只会写入存储在数组中的值。您可能可以执行类似 declare -p AARR,然后 x=$(creatAARR); declare -A "NEW_ARR=$x" 的操作,但您真的正在尝试在 shell 中使用非常不像 shell 的代码。 - chepner
是的,@chepner说得对。我添加了一个答案。它适用于我的情况。 - Alterecho
显示剩余4条评论
2个回答

5

return 只接受整数并设置函数的 退出状态

Shell 命令实际上不能返回值。如果您想将信息传递给函数调用者,有几种选项可供选择:

  • 您可以 您的返回值 print 出来,但这需要您正确格式化输出并让调用者正确解析它。对于关联数组,有太多错误的方法;我不建议这样做。
  • 在 Zsh 中,有一种约定,即要传达返回值,函数可以将 $REPLY 设为标量值或 $reply 设为数组。不幸的是,没有传递 关联 数组的约定。当然,您可以将键-值对简单地作为元素放入非关联数组 $reply 中,然后让调用者将其转换为关联数组或将其包装在关联数组中,但这会打破约定,因此可能违反调用者的期望。
  • 我认为最好的方法是让调用者指定一个关联数组的名称,然后您可以使用值填充它。当您想返回任何类型的 多个 值时,这也非常方便,因为您可以让调用者指定多个变量名。

您可以使用以下最后一种方法:

% creatAARR() {
  # Restrict $name to function scope.
  local name=$1

  # Delete $1, so $@ becomes the other args.
  shift

  # Assign elements to array. 
  set -A "$name" "$@"
}
% typeset -A AARR=()  # Declare assoc. array
% creatAARR AARR k1 2 k2 4
% typeset -p1 AARR    # Print details
typeset -A AARR=( 
  [k1]=2 
  [k2]=4 
)

嗯,这听起来也是一个不错的计划。会测试一下。谢谢。 - Alterecho
@Alterecho,你认为你能接受我的回答吗? - Marlon Richert
关联数组基本上只是带有成对键/值的常规数组。因此,您可以使用 $reply 作为结果数组,然后让调用者将其简单地转换为关联数组:typeset -A myaarr=("${reply[@]}") - mattmc3
是的,但这不是Zsh代码的惯例。如果您查看与Zsh一起分发的函数,它们几乎总是(不,我没有彻底检查)为关联数组使用命名参数,而不是$reply - Marlon Richert
谢谢你的建议!我已经更新了我的答案,包括了它。 - Marlon Richert

0

我已经能够通过这个满足我的需求:

declare -A VAR1
declare -A VAR2

TYPE_VAR1="TYPE_VAR1"
TYPE_VAR2="TYPE_VAR2"

creatAARR() {
    declare -A AARR=([k1]=2 [k2]=4)
        case $1 in 
    "$TYPE_VAR1")
        set -A VAR1 ${(kv)AARR}
    ;;
    "$TYPE_VAR2")
        set -A VAR2 ${(kv)AARR}
    ;;
    esac
}

creatAARR $TYPE_VAR1 $VAR1

echo "${(kv)VAR1}"

return

也许还有更好的方法,但这是目前对我有效的方法。 欢迎随时添加你自己的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接