web-dev-qa-db-fra.com

comment passer tableau en fonction et les mises à jour de tableau sont reflétées en dehors de la fonction

J'essaie de passer un tableau dans une fonction et toutes les modifications apportées au tableau sont reflétées à l'extérieur de la fonction

function update_array()
{   
    ${1[0]}="abc" # trying to change zero-index array to "abc" , 
                  #  bad substitution error


}

foo=(foo bar)

update_array foo[@]

for i in ${foo[@]}
    do
       echo "$i" # currently changes are not reflected outside the function

    done

Mes questions sont

1) Comment puis-je accéder au tableau d'index, par exemple: tableau d'index zéro, dans la fonction, quelle est sa syntaxe

2) Comment puis-je apporter des modifications à ce tableau d'index afin que les modifications soient reflétées hors site également

2
Computernerd

Plusieurs problèmes, dans l’ordre logique de la résolution:

  • Style (bête noire)
  • Avec votre instruction ${...} dans update_array(), la syntaxe ${..} consiste à tiliser une variable et non à la définir.

    Exemple:

    foo[0]=abc  # assigns 'abc' to foo[0]
    
  • Contournant cela, le nom du tableau est stocké dans une variable.

    Ne fonctionne pas:

    $1[0]=abc
    

    Travail:

    declare -g "$1[0]=abc"  # -g arg is for a global variable
    
  • Passer un argument à update_array() devrait transmettre le nom de la variable (foo dans ce cas), pas le contenu du tableau. foo[@] n'a rien de spécial, c'est une chaîne complètement normale (en Bash).

  • L'extension de variable avec ${foo[@]} devrait être double.

La version de travail du code est ci-dessous:

update_array() {   
    declare -g "$1[0]=abc"
}

foo=(foo bar)

update_array foo

for i in "${foo[@]}"; do
    echo "$i"
done

## Following line added by me for further clarification
declare -p foo

qui imprime correctement:

abc
bar
declare -a foo='([0]="abc" [1]="bar")'
3
kiri

La déclaration de variables peut ne pas être nécessaire dans Bash.1 Oui, vous pouvez utiliser declare/typeset pour plus de contrôle sur vos variables bash. Je pense donc qu'il n'est pas nécessaire de créer une fonction uniquement pour déclarer un nouveau tableau.

Ce script ci-dessous illustre une définition directe du tableau:

#!/bin/bash
function define_array_elements() {
# You can note the array elements being defined directly, without a prior 
# definition of the variable.
for i in {1..10}; do
    var_name[$i]="Field $i of the list"
done
}

define_array_elements > /dev/null

for i in {1..10}; do
    echo "Field $i is: ${var_name[$i]}"
done

(Un exemple emprunté à Comment déclarer un tableau sans le définir? avec juste une petite modification.)

0
precise

La réponse courte est: vous ne pouvez pas. Bash n'a pas de moyen de passer des variables par référence, il n'y a donc pas de moyen générique de le faire; il vous reste des hacks (laids) incluant indirection et/ou eval.

La prochaine version 4.3 de bash présentera les variables nameref, qui vous permettent de passer des variables par référence, mais même cette fonctionnalité n’est pas satisfaisante car vous risquez toujours la collision de noms.

# example of passing variables by reference in bash 4.3
update_array() {
    declare -n array=$1
    array[0]=abc
}

foo=( foo bar )

update_array foo

printf '<%s>\n' "${foo[@]}" # outputs <abc> and <bar>

Dans cet exemple, si le tableau s'appelait array au lieu de foo, il échouerait car declare -n array=array est une erreur (declare: array: nameref variable self references not allowed).

Voir http://mywiki.wooledge.org/BashFAQ/006 pour d'autres hacks.

0
geirha