Quelle est la façon la plus correcte de passer un tableau à une fonction?

8

Considérons que j'ai un très grand tableau $large_list, existe-t-il un moyen d'écrire une fonction qui prendra le tableau en argument? Par exemple:

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

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

Quelle est la stratégie habituelle pour faire quelque chose comme ça? J'ai essayé de donner la variable $large_listmais elle était vide.

Je suis prêt à modifier la fonction pour l'adapter à tout changement dans la liste des arguments.

Pour mémoire, j'utilise ksh88, et je recherche des réponses aussi portables que possible.


EDIT : Jusqu'à présent, le mieux que j'ai pu trouver est de parcourir le tableau et d'envoyer chaque élément comme argument à la fonction. Cela semble incroyablement laid et sujet aux erreurs, sans parler du fait qu'il atteindra rapidement une limite. Voici ce que j'ai fait:

foo () {
    echo $*
}

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

eval $cmd

N'y a-t-il pas quelque chose de mieux à faire?

rahmu
la source
1
Je ne connais pas ksh88, mais si vous avez besoin de passer le tableau entier par valeur, avez-vous essayé func "${array[@]}"? Si vous avez seulement besoin de passer un élément, passez simplement l'élément - pas besoin de le rendre plus compliqué en passant un tableau et un index.
jw013
J'ai essayé la syntaxe que vous avez suggérée, mais cela n'a pas fonctionné :(
rahmu
1
J'étais fatigué et confus. J'avais essayé "${array[$@]}. Votre suggestion fonctionne réellement. Mea culpa.
rahmu

Réponses:

10

Pour passer les éléments du tableau comme arguments à la fonction, utilisez la syntaxe ksh pour développer les éléments du tableau sous forme de liste.

work_on_array "${myarray[@]}"

Le [@]suffixe en fait une extension de tableau. Les guillemets doubles protègent chaque élément contre toute nouvelle expansion (division et globalisation). Le résultat de l'expansion n'est pas en général un mot comme c'est généralement le cas avec les guillemets doubles, mais autant de mots qu'il y a d'éléments dans le tableau.

Le N ème élément du tableau est alors . Pour y accéder, vous devez utiliser ; voir Utiliser une référence de variable "à l'intérieur" d'une autre variable${N}eval

Gilles 'SO- arrête d'être méchant'
la source
Merci. Question: si le résultat de l'expansion n'est pas un mot, pourquoi les guillemets sont-ils nécessaires? Peuvent-ils être omis? Appliquez-vous simplement vos conseils de «toujours citer sauf si vous avez une bonne raison de ne pas le faire»? : p
rahmu
1
@rahmu Les guillemets sont nécessaires pour éviter le fractionnement et la globalisation sur des éléments individuels. Considérons myarray=("hello world" wibble)(2 éléments, dont le premier contient un espace): work_on_array "${myarray[@]}"passe 2 paramètres hello worldet wibble; work_on_array ${myarray[@]}passe 2 paramètres hello, worldet wibble. Et avec myarray=(*), work_on_array ${myarray[@]}passe la liste des fichiers dans le répertoire courant. (C'est donc l'un des nombreux cas où mes conseils font une différence pratique.)
Gilles 'SO- arrête d'être méchant'
Corrigez-moi si je me trompe, mais je pense qu'il y a une faute de frappe dans ce que vous avez écrit: l'extension non citée passe 3 paramètres, pas 2.
rahmu
1
@rahmu Il y a deux paramètres: la peur et la surprise… et l'efficacité impitoyable. (En d' autres termes, vous avez raison, il y a une faute de frappe: hello, worldet wibblefaire 3 paramètres.)
Gilles de l' arrêt SO- étant le mal "
4

Il y a un moyen dans bash 4.3+, qui vient probablement de 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

Voir aussi declare -n.

Edouard Thiel
la source
Huh, intéressant. Oui, cela vient de ksh, et fonctionne en mksh non modifié.
mirabilos
1

Cela dépend du Korn Shell… les récentes versions AT&T ksh93 et ​​mksh prennent en charge ceci:

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

    echo "${arr[idx]}"
}

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

Dans mon interpréteur de commandes actuel, cela produit «b».

mirabilos
la source