web-dev-qa-db-fra.com

Comment passer un tableau en argument de fonction?

Luttant pendant un moment en passant un tableau en argument mais cela ne fonctionne pas quand même. J'ai essayé comme ci-dessous:

#! /bin/bash

function copyFiles{
   arr="$1"
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one" "two" "three")

copyFiles $array

Une réponse avec des explications serait bien.

Edit: Fondamentalement, j'appellerai éventuellement la fonction à partir d'un autre fichier de script. Plz expliquer les contraintes si possible.

41
Ahsanul Haque
  • Développer un tableau sans index ne donne que le premier élément, utilisez

    copyFiles "${array[@]}"
    

    au lieu de

    copyFiles $array
    
  • Utiliser un she-bang

    #!/bin/bash
    
  • Utilisez la syntaxe de fonction correcte

    Les variantes valides sont

    function copyFiles {…}
    function copyFiles(){…}
    function copyFiles() {…}
    

    au lieu de

    function copyFiles{…}
    
  • Utilisez la bonne syntaxe pour obtenir le paramètre de tableau

    arr=("$@")
    

    au lieu de

    arr="$1"
    

Donc

#!/bin/bash
function copyFiles() {
   arr=("$@")
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one" "two" "three")

copyFiles "${array[@]}"

La sortie est (mon script s'appelle foo)

$ ./foo   
one
two
three
69
A.B.

Si vous voulez passer un ou plusieurs arguments ET un tableau, je propose cette modification au script de @A.B.
Tableau devrait être le dernier argument et seulement un tableau peut être passé

#!/bin/bash
function copyFiles() {
   local msg="$1"   # Save first argument in a variable
   shift            # Shift all arguments to the left (original $1 gets lost)
   local arr=("$@") # Rebuild the array with rest of arguments
   for i in "${arr[@]}";
      do
          echo "$msg $i"
      done
}

array=("one" "two" "three")

copyFiles "Copying" "${array[@]}"

Sortie:

$ ./foo   
Copying one
Copying two
Copying three
14
SBF

Vous pouvez également passer le tableau comme référence. c'est à dire.:

#!/bin/bash

function copyFiles {
   local -n arr=$1

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

array=("one" "two" "three")

copyFiles array

mais notez que toutes les modifications apportées à arr seront apportées à array.

14
user448115

Il y a quelques problèmes. Voici le formulaire de travail:

#!/bin/bash
function copyFiles {
   arr=( "$@" )
   for i in "${arr[@]}";
      do
          echo "$i"
      done

}

array=("one" "two" "three")
copyFiles "${array[@]}"
  • Il doit y avoir au moins un espace entre la déclaration de la fonction et {

  • Vous ne pouvez pas utiliser $array, car array est un tableau et non une variable. Si vous voulez obtenir toutes les valeurs d'un tableau, utilisez "${array[@]}"

  • Dans votre déclaration de fonction principale, vous avez besoin de arr="$@" car "${array[@]}" sera étendu aux valeurs indexées séparées par des espaces. Si vous utilisez $1, vous n'obtiendrez que la première valeur. Pour obtenir toutes les valeurs, utilisez arr="$arr[@]}".

7
heemayl

Voici un exemple légèrement plus grand. Pour plus d'explications, voir les commentaires dans le code.

#!/bin/bash -u
# ==============================================================================
# Description
# -----------
# Show the content of an array by displaying each element separated by a
# vertical bar (|).
#
# Arg Description
# --- -----------
# 1   The array
# ==============================================================================
show_array()
{
    declare -a arr=("${@}")
    declare -i len=${#arr[@]}
    # Show passed array
    for ((n = 0; n < len; n++))
    do
        echo -en "|${arr[$n]}"
    done
    echo "|"
}

# ==============================================================================
# Description
# -----------
# This function takes two arrays as arguments together with their sizes and a
# name of an array which should be created and returned from this function.
#
# Arg Description
# --- -----------
# 1   Length of first array
# 2   First array
# 3   Length of second array
# 4   Second array
# 5   Name of returned array
# ==============================================================================
array_demo()
{
    declare -a argv=("${@}")                           # All arguments in one big array
    declare -i len_1=${argv[0]}                        # Length of first array passad
    declare -a arr_1=("${argv[@]:1:$len_1}")           # First array
    declare -i len_2=${argv[(len_1 + 1)]}              # Length of second array passad
    declare -a arr_2=("${argv[@]:(len_1 + 2):$len_2}") # Second array
    declare -i totlen=${#argv[@]}                      # Length of argv array (len_1+len_2+2)
    declare __ret_array_name=${argv[(totlen - 1)]}     # Name of array to be returned

    # Show passed arrays
    echo -en "Array 1: "; show_array "${arr_1[@]}"
    echo -en "Array 2: "; show_array "${arr_2[@]}"

    # Create array to be returned with given name (by concatenating passed arrays in opposite order)
    eval ${__ret_array_name}='("${arr_2[@]}" "${arr_1[@]}")'
}

########################
##### Demo program #####
########################
declare -a array_1=(Only 1 Word @ the time)                                       # 6 elements
declare -a array_2=("Space separated words," sometimes using "string paretheses") # 4 elements
declare -a my_out # Will contain output from array_demo()

# A: Length of array_1
# B: First array, not necessary with string parentheses here
# C: Length of array_2
# D: Second array, necessary with string parentheses here
# E: Name of array that should be returned from function.
#          A              B             C              D               E
array_demo ${#array_1[@]} ${array_1[@]} ${#array_2[@]} "${array_2[@]}" my_out

# Show that array_demo really returned specified array in my_out:
echo -en "Returns: "; show_array "${my_out[@]}"
2
Ulf Oreborn

Aussi laid que cela puisse paraître, voici une solution de contournement qui fonctionne tant que vous ne passez pas explicitement un tableau, mais une variable correspondant à un tableau:

function passarray()
{
    eval array_internally=("$(echo '${'$1'[@]}')")
    # access array now via array_internally
    echo "${array_internally[@]}"
    #...
}

array=(0 1 2 3 4 5)
passarray array # echo's (0 1 2 3 4 5) as expected

Je suis sûr que quelqu'un peut proposer une implémentation plus nette de l'idée, mais j'ai trouvé que c'était une meilleure solution que de passer un tableau en tant que "{array[@]"} puis de l'y accéder en interne à l'aide de array_inside=("$@"). Cela devient compliqué quand il y a d'autres paramètres positionnels/getopts. Dans ces cas, j'ai d'abord dû déterminer, puis supprimer les paramètres non associés au tableau en utilisant une combinaison de shift et de la suppression d'éléments du tableau.

Une perspective puriste considère probablement cette approche comme une violation de la langue, mais, d'une manière pragmatique, cette approche m'a évité beaucoup de chagrin. Sur un sujet connexe, j'utilise également eval pour affecter un tableau construit en interne à une variable nommée en fonction d'un paramètre target_varname que je transmets à la fonction:

eval $target_varname=$"(${array_inside[@]})"
0
Blake Schultze

Le meilleur moyen est de passer comme argument de position. Rien d'autre. Vous pouvez passer en tant que chaîne, mais de cette façon peut causer des problèmes. Exemple:

array=(one two three four five)

function show_passed_array(){
  echo $@
}

ou

function show_passed_array(){
  while $# -gt 0;do
    echo $1;shift
  done
}

    show_passed_array ${array[@]}

sortie:

  one two three four five

Vous voulez dire que si la valeur du tableau a des symboles d'espace, vous devez d'abord citer les éléments avant de passer pour accéder à la valeur par index dans la fonction, utilisez $ 1 $ 2 $ 3 ... paramètres de position. Où index 0 -> 1, 1 -> 2, ... Pour itérer l’accès, il est préférable d’utiliser toujours $ 1 et après Shift. Rien de plus n'est nécessaire. Vous pouvez passer des arguments sans aucun tableau comme celui-ci:

show_passed_array one two three four five

bash media construit automatiquement un tableau à partir des arguments passés qui les ont passés à fonction, puis vous avez des arguments de position. De plus, lorsque vous écrivez $ {array [2]}, vous écrivez réellement les arguments suivants un deux trois quatre et vous les transmettez à la fonction. Donc, ces appels sont équivalents.

0
Anatoly