Каков наиболее правильный способ передачи массива в функцию?

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

Разве нет ничего лучше?

rahmu
источник
1
Я не знаком с ksh88, но если вам нужно передать весь массив по значению, вы пробовали func "${array[@]}"? Если вам нужно передать только один элемент, просто передайте элемент - не нужно делать его более сложным, передавая массив и индекс.
jw013
Я попробовал предложенный вами синтаксис, но он не сработал :(
rahmu
1
Я был уставшим и растерянным. Я пытался "${array[$@]}. Ваше предложение действительно работает. Моя вина.
раму

Ответы:

10

Чтобы передать элементы массива в качестве аргументов функции, используйте синтаксис ksh, чтобы развернуть элементы массива в виде списка.

work_on_array "${myarray[@]}"

[@]Суффикс делает это расширение массива. Двойные кавычки защищают каждый элемент от дальнейшего расширения (расщепления и сглаживания). Результатом раскрытия обычно является не одно слово, как обычно с двойными кавычками, а столько слов, сколько элементов в массиве.

N - й элемент массива затем . Чтобы получить к нему доступ, вам необходимо использовать ; см. Использование ссылки на переменную "внутри" другой переменной.${N}eval

Жиль "ТАК - перестань быть злым"
источник
Спасибо. Вопрос: если результат расширения не одно слово, зачем нужны кавычки? Могут ли они быть опущены? Вы просто применяете ваш совет «всегда цитируйте, если у вас нет веских причин не делать этого»? : p
rahmu
1
@rahmu Кавычки нужны, чтобы избежать расщепления и слияния отдельных элементов. Рассмотрим myarray=("hello world" wibble)(2 элемента, первый из которых содержит пробел): work_on_array "${myarray[@]}"передает 2 параметра hello worldи wibble; work_on_array ${myarray[@]}передает 2 параметра hello, worldи wibble. И с myarray=(*), work_on_array ${myarray[@]}передает список файлов в текущем каталоге. (Следовательно, это один из многих случаев, когда мой совет имеет практическое значение.)
Жиль «ТАК - перестань быть злым»
Поправьте меня, если я ошибаюсь, но я полагаю, что в том, что вы написали, есть опечатка: расширение без
кавычек
1
@rahmu Есть два параметра: страх и удивление ... и безжалостная эффективность. (Другими словами, вы правы, есть опечатка: hello, worldи wibbleсделать 3 параметра.)
Жиля 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 без изменений.
Мирабилось
1

Зависит от оболочки Korn… последние версии 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

В моей текущей оболочке это выдает «b».

mirabilos
источник