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.
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
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
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.
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[@]}"
.
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[@]}"
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[@]})"
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.