将数组传递给函数的最正确方法是什么?


8

考虑我有一个非常大的数组$large_list,有没有办法编写一个将数组作为参数的函数?例如:

echo_idx_array () {
    arr="$1"
    idx="$2"

    echo "${arr[$idx]}"
}

做这样的事情的通常策略是什么?我试着给变量,$large_list但它是空的。

我愿意修改该函数以使其适应参数列表中的任何更改。

作为记录,我正在使用ksh88,并且正在寻找尽可能便携的答案。


编辑:到目前为止,我能想到的最好的办法是遍历数组并将每个元素作为参数发送给函数。这看起来非常丑陋且容易出错,更不用说它一定会很快达到某个极限。这是我所做的:

foo () {
    echo $*
}

cmd="foo "
while [[ $i -lt $MAX_ARR_SIZE ]]; do
    cmd="$cmd ${large_list[$i]}"
    ((i=i+1))
done

eval $cmd

有没有更好的事情要做?


1
我不熟悉ksh88,但是如果您需要按值传递整个数组,您是否尝试过func "${array[@]}"?如果只需要传递一个元素,则只需传递该元素-无需通过传递数组和索引来使其更加复杂。
2012年

我尝试了您建议的语法,但没有用:(
rahmu 2012年

1
我感到疲倦和困惑。我试过了"${array[$@]}。您的建议确实有效。Mea culpa。
rahmu 2012年

Answers:


10

要将数组元素作为函数的参数传递,请使用ksh语法将数组的元素扩展为列表。

work_on_array "${myarray[@]}"

所述[@]后缀使得该阵列的扩展。双引号保护每个元素免于进一步扩展(分裂和浮空)。扩展的结果通常不像通常使用双引号那样包含一个单词,而是与数组中的元素一样多的单词。

然后,数组的第N个元素是。要访问它,您需要使用; 请参见在另一个变量“内部”使用变量引用${N}eval


谢谢。问题:如果扩展的结果不是一个单词,为什么需要引号?可以省略吗?您是否只是在使用“总是报价,除非您有充分的理由不这样做”的建议?:p
rahmu 2012年

1
@rahmu需要使用引号,以避免在单个元素上出现拆分和模糊。考虑myarray=("hello world" wibble)(2个元素,其中第一个元素包含空格):work_on_array "${myarray[@]}"传递2个参数hello worldwibblework_on_array ${myarray[@]}传递2个参数helloworldwibble。并用myarray=(*)work_on_array ${myarray[@]}通过文件的当前目录列表。(因此,这是我的建议在实际中
有所作为

纠正我,如果我错了,但我相信有一个在你写一个错字:未加引号扩展经过3参数,可以不是2
rahmu

1
@rahmu有两个参数:恐惧和惊奇……以及无情的效率。(换句话说,您是对的,这里有一个错别字:helloworld并输入wibble3个参数。)
Gilles'SO-别再作恶了'

4

bash 4.3+中有一种方法,可能来自ksh:

echo_idx_array () # array index
{
    local -n array=$1     # add nameref attribute
    local idx=$2
    echo "${array[idx]}"
}

$ names=(one two three four)
$ echo_idx_array names 2
three
$ days=([monday]=eggs [tuesday]=bread [sunday]=jam)    # associative array
$ echo_idx_array days sunday
jam

另请参阅declare -n


嗯,有趣。是的,它来自ksh,并且在未经修改的mksh中工作。
mirabilos 2014年

1

取决于Korn Shell…最新的AT&T ksh93和mksh版本支持此功能:

function echo_idx_array {
    nameref arr=$1
    idx=$2

    echo "${arr[idx]}"
}

set -A test -- a b c
echo_idx_array test 1

在我当前的shell中,这确实输出“ b”。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.