如何将数组文本传递给 bash 函数

How to pass array literal to a bash function

提问人:greenoldman 提问时间:11/23/2021 最后编辑:greenoldman 更新时间:11/23/2021 访问量:1073

问:

首先,我阅读了有关传递数组的一般知识 - 我看到的所有示例都首先为数组创建了临时变量,然后传递了它。摘自 https://stackoverflow.com/a/26443029/210342

show_value () # array index
{
    local -n myarray=$1
    local idx=$2
    echo "${myarray[$idx]}"
}

shadock=(ga bu zo meu)
show_value shadock 2

有没有办法将数组直接作为文字传递,即不创建临时变量?

我尝试了简单的方法,只是用数据替换名称,但我对“(”的语法错误。

更新

我将 openSUSE Leap 15.3 和 bash 4.4 一起使用。上面的代码当然有效,但我想将调用更改为:

show_value (ga bu zo meu) 2

即直接传递数组数据(不使用额外的变量)。

数组 bash 函数 参数传递

评论

1赞 wjandrea 11/23/2021
你说的“字面意思”是什么意思? ?根据 chepner 的说法,“bash 中没有数组文字这样的东西”。declare -p shadock
1赞 wjandrea 11/23/2021
你这样做想解决什么问题?
1赞 glenn jackman 11/23/2021
syntax error on "("-- 你用什么 shell 来运行这段代码? 或?shbash
1赞 dan 11/23/2021
此代码没有错。我测试并得到了.zo
2赞 Gordon Davisson 11/23/2021
根据定义,函数(或命令或其他)的参数是字符串。不能将任何其他类型的数据结构作为参数传递。因此,“传递数组”的选择或多或少是:传递元素(每个元素作为单独的参数)并让函数将参数列表(或其中的一部分)视为数组;传递数组变量的名称(在您给出的示例中执行了哪些操作);或者以某种方式将数组转换(“pickle”)为单个字符串,并让函数将该字符串解析为单独的元素。

答:

1赞 John Kugelman 11/23/2021 #1

函数参数的结构不足以处理嵌套数据结构(如数组)。参数是字符串的平面列表,仅此而已。

您可以内联扩展数组:

show_value "${shadock[@]}" 2

但是,分隔符会丢失。无法知道数组的开始和结束位置,因为它扩展为:

show_value ga bu zo meu 2

你必须自己弄清楚数组边界。选项包括:

  • 如果该命令只有一个数组参数,请将其设为最后一个数组参数。这是许多采用多个文件名的传统 UNIX 工具所做的。 示例: , .ls <file>...chmod <mode> <file>...

  • 如果前面/后面有固定数量的参数,则可以将数组放在中间,以便可以明确地确定数组的位置。例:。cp <file>... <dir>

  • 如果有多个数组,则可以要求用户用 分隔它们。许多 git 更复杂的子命令都是这样做的。--

我告诫不要将数组名称作为参数。这是一种非常特定于 shell 的技术。这将使将函数变成一个成熟的脚本或二进制文件变得困难。

评论

0赞 greenoldman 11/23/2021
谢谢你的解释和提示,我确实颠倒了参数的顺序,所以尾巴会变成数组。
2赞 glenn jackman 11/23/2021 #2

如果要更改参数的顺序:

show_value () #  index array_element [...]
{
    local idx=$1
    local -a myarray=("${@:2}")
    echo "${myarray[$idx]}"
}

然后

shadock=(ga bu zo meu)
show_value 2 "${shadock[@]}"   # => zo

如果要将索引保留为最后一个参数,则

show_value () #  array_element [...] index
{
    local -a myarray=("${@:1:$#-1}")
    local idx=${!#}
    echo "${myarray[$idx]}"
}
show_value "${shadock[@]}" 2   # => zo

local -n myarray=$1肯定比这一切整洁得多,不是吗?它还将更快,更节省内存 - 您不必复制所有数据。

1赞 Philippe 11/23/2021 #3

你能考虑一下这个语法吗:

show_value () # array index
{
    local -a myarray=$1
    local idx=$2
    echo "${myarray[$idx]}"
}

show_value "(ga bu zo meu)" 2

出于安全原因,您需要确定传递到函数中的数组的内容。