# \[shell\] Passage d'un tableau à une fonction

**URL:** <https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282>\
**Category:** Programmation\
**Created:** [Février 20, 2016, 5:27 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282 "2016-02-20T17:27:36Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Février 20, 2016, 5:27 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/1 "2016-02-20T17:27:36Z")

</div>

Passer un tableau à une fonction, une fonctionnalité de base pour les langages modernes, n’est pas si évident en shell. Surtout en bash comme vous le verrez plus bas. Si j’ai facilement trouvé une solution en ksh, il m’a fallu deux jours de réflexion et d’essais-erreurs pour y arriver en bash.

Objectif:[ol]  
[li]créer deux tableaux (arrays)[/li]  
[li]passer ces tableaux à une fonction qui, pour l’exemple, va simplement afficher leur contenu.[/li]  
[li]assurer une portée _locale_ des tableaux à l’intérieur de la fonction.[/li][/ol]

Solutions:[ul]  
[li]On commence par le plus facile (ksh):

[code]#!/usr/bin/ksh

# passage de tableau par référence à une fonction

function print\_tableau {  
# copie locale du tableau par référence aux paramètres $1 $2 etc…  
typeset -n tab\_local=$1

```
# affichage des éléments du tableau local
echo; echo "$1"
for item in ${!tab_local[@]}; do
    echo " [${item}] => ${tab_local[$item]}"
done

```

}

# affectation des tableaux

```
couleurs=('Rose' 'Gris clair' 'Vert')
etats=('Liquide' 'Solide' 'Gaz')

```

# appel à la fonction avec passage des tableaux

```
print_tableau "couleurs"
print_tableau "etats"

```

# vérification que le tableau “local” tab\_local de la fonction n’existe plus ici

```
echo; echo "Contenu de tab_local -->${tab_local[*]}<--"

```

[/code]  
[/li]  
[li]Un peu (!) plus ardu en bash:

[code]#!/bin/bash

# passage de tableau par référence à une fonction

function print\_tableau {  
# On met le IFS (Internal Field Separator) à NULL  
# ceci est indispensable pour préserver l’espace dans “Gris clair”  
# lors de l’expansion ${couleurs[\*]} qui a lieu plus bas  
OLD\_IFS=$IFS  
IFS=’’

```
# On crée une chaîne contenant "couleurs[*]"
local tab_str="$1[*]"

# on réaffecte le contenu du tableau $colors à tab_local par référence indirecte
    # une copie locale des tableaux "couleurs" et "etats" en quelque sorte
    # tab_local=(${couleurs[*]})
local tab_local=(${!tab_str})

# remise de IFS à sa valeur par défaut
IFS=$OLD_IFS

# affichage des éléments du tableau local
echo; echo "$1"
for item in ${!tab_local[@]}; do
    echo " [${item}] => ${tab_local[$item]}"
done

```

}

# affectation des tableaux

```
couleurs=('Rose' 'Gris clair' 'Vert')
etats=('Liquide' 'Solide' 'Gaz')

```

# appel à la fonction avec passage des tableaux

```
print_tableau "couleurs"
print_tableau "etats"

```

# vérification que le tableau “local” tab\_local de la fonction n’existe plus ici

```
echo; echo "Contenu de tab_local -->${tab_local[*]}<--"

```

[/code]  
[/li]  
[li]Liens divers  
[unix.com/shell-programming-s … ction.html](http://www.unix.com/shell-programming-scripting/61370-bash-ksh-passing-array-function.html)  
[tldp.org/LDP/abs/html/bashver2.html#VARREFNEW](http://tldp.org/LDP/abs/html/bashver2.html#VARREFNEW)[/li][/ul]

Ceci peut aussi servir pour “copier” un tableau. Le réaffecter à une autre variable.

Vous comprenez pourquoi je préfère ksh? :smt002

---

<div class="post-metadata">

**Author:** ![ed](https://www.debian-fr.org/user_avatar/www.debian-fr.org/ed/32/5886_2.png) [@ed](https://www.debian-fr.org/u/ed)\
**Post date:** [Février 20, 2016, 5:27 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/2 "2016-02-20T17:27:46Z")

</div>

Essaye en zsh, tu va être surpris 😃

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 5:27 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/3 "2016-02-20T17:27:48Z")

</div>

> [@](#):
>
> Essaye en zsh, tu va être surpris 😃

J’ai deja essaye de lui dire ^^

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Février 20, 2016, 5:27 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/4 "2016-02-20T17:27:49Z")

</div>

Je ne demande qu’à voir. Allez-y, soumettez votre solution pour le problème ci-dessus. J’avoue que votre suggestion m’a poussé à aller voir ce qu’on dit de zsh sur le net et que ça m’a mis l’eau à la bouche. Mais, pour l’instant, je n’ai pas le courage de me mettre un troisième shell sur le dos.

Si vous vous prenez au jeu, on pourrait créer, à titre d’exercice ludique, une petite librairie de fonctions sur les arrays:

array\_print  
array\_sort  
array\_search  
array\_merge

etc…

Le défi est lancé 😉

---

<div class="post-metadata">

**Author:** ![ed](https://www.debian-fr.org/user_avatar/www.debian-fr.org/ed/32/5886_2.png) [@ed](https://www.debian-fr.org/u/ed)\
**Post date:** [Février 20, 2016, 5:27 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/5 "2016-02-20T17:27:58Z")

</div>

Perso j’en ai pas besoin, mais honetement, regarde zsh, les autre shell sont inutiles 🙂

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Février 20, 2016, 5:27 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/6 "2016-02-20T17:27:59Z")

</div>

[quote=“ed”]Perso j’en ai pas besoin, …[/quote]C’est clair que c’est juste un exercice de style et que si on a besoin de variables-tableaux on ferait mieux de se tourner vers Perl, Python, PHP-CLI ou même awk qui gère ça très bien.

[quote=“ed”]… regarde zsh, les autre shell sont inutiles 🙂[/quote]J’ai regardé et ça m’a plu. Faudrait que je prenne le temps de tester. Il y a aussi le c shell qui a ses aficionados. Un jour sans doute…

---

<div class="post-metadata">

**Author:** ![usinagaz](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/u/ecae2f/32.png) [@usinagaz](https://www.debian-fr.org/u/usinagaz)\
**Post date:** [Février 20, 2016, 5:29 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/7 "2016-02-20T17:29:50Z")

</div>

> [@](#):
>
> Passer un tableau à une fonction, une fonctionnalité de base pour les langages modernes, n’est pas si évident en shell. Surtout en bash comme vous le verrez plus bas. Si j’ai facilement trouvé une solution en ksh, il m’a fallu deux jours de réflexion et d’essais-erreurs pour y arriver en bash.

bonsoir,  
malheureusement, lire le manuel bash tout ce qui concerne section tableau t’aurais pris qu’une demi-heure, sans rien tester avant d’avoir trouver lol 😉  
attention pour les tableaux en bash, il y a un espace(+) entre parenthèse + contenu + parenthèse. (je crois même qu’il faut faire un echo dés fois, style dans la fonction ( “`echo $*`” ) [\<- c’est même plus simple que ça encore je crois bien], enfin ya plus simple, me souviens plus trés bien.  
C’est trés facile de passer un tableau en bash, mais sans savoir comment ou en l’ayant oublié, on cherche longtemps, sans le manuel, c’est vrai.

[quote]  
array\_print  
array\_sort  
array\_search  
array\_merge[/quote]  
biensur pourquoi pas, je les ai déjà dans un coin…  
dans le manuel (pas man), il y a de nombreux examples qui déjà mâchent bien le travail je crois.  
petite question pur ed :  
est-ce qu’on peut lancer un script autre que bash (ksh ?), via `` ou une fonction intégrée le tout via php ? à tester.

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Février 20, 2016, 5:29 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/8 "2016-02-20T17:29:53Z")

</div>

[quote=“usinagaz”]bonsoir,  
malheureusement, lire le manuel bash tout ce qui concerne section tableau t’aurais pris qu’une demi-heure, sans rien tester avant d’avoir trouver lol 😉  
attention pour les tableaux en bash, il y a un espace(+) entre parenthèse + contenu + parenthèse. (je crois même qu’il faut faire un echo dés fois, style dans la fonction ( “`echo $*`” ) [\<- c’est même plus simple que ça encore je crois bien], enfin ya plus simple, me souviens plus trés bien.  
C’est trés facile de passer un tableau en bash, mais sans savoir comment ou en l’ayant oublié, on cherche longtemps, sans le manuel, c’est vrai.[/quote]

Je n’ai pas trop bien compris ta solution. Pourrais-tu développer en nous donner un exemple de passage de tableau en bash?

---

<div class="post-metadata">

**Author:** ![usinagaz](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/u/ecae2f/32.png) [@usinagaz](https://www.debian-fr.org/u/usinagaz)\
**Post date:** [Février 20, 2016, 5:29 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/9 "2016-02-20T17:29:57Z")

</div>

bonjour,  
oui, en fait c’est simple, il faut juste savoir un truc:  
en bash les variables ne sont pas typées.

ça veut dire que passer un tableau à une fonction, ce n’est pas exactement lui passer la réference d’un tableau, mais lui passer son contenu.  
C’est ta fonction que tu conçois comme devant traiter la suite de variable comme un tableau, je pense.

exemple: mettons la fonction testTab(){}

on dit que tab=( 1 2 3 4 ) ou tab=(1 2 3 4) // tu avais raison, peu importe les espaces.

Que tu fasse  
testTab ${tab[\*]} ou  
testTab 1 2 3 4  
ça revient au même, on passe un contenu de tableau ou une suite d’argument à la fonction, et non un tableau en tant que tel.

Reste à reformer le tableau dans la fonction:  
tab2=( $\* ) tout simplement, ou  
tab3=( `echo $*` ).  
Si c’est sur `echo $*` que tu me demandais une explication, je ne sais plus pourquoi je faisais ça à un moment, mais il y avait une raison, peut-être mauvaise.

Voici une fonction qui pourrait faire office de array\_sort, pour les autres, je retrouve plus, ou c’est pas montrable ☹; celle-ci est issue du manuel, si je me souviens bien :

[code]#!/bin/bash

# Tri à bulle, des éléments d’un tableau .

tri\_tableau() {

# fonction interne, interversion des index -------------------------------------------------

echange()  
{  
# échange deux membres d’un tableau  
local temp=${tab[$1]} # Stockage temporaire  
# pour les éléments à échanger.  
tab[$1]=${tab[$2]}  
tab[$2]=$temp

```
return

```

}

# ------------------------------------------------------------------

# test si un argument ----------------------------------------------------------------------

[! -n “$1”] && {  
echo "Absense de paramètre, spécifier un tableau"  
exit $ERR\_F\_PARAM  
}  
tab=( $\* ) # récupére le tableau  
nombre\_d\_elements=${#tab[@]}  
let "comparaisons = $nombre\_d\_elements - 1"  
index=1 # Nombre de tours.  
while [“$comparaisons” -gt 0] # Début de la boucle externe.  
do  
index=0 # Réinitialise l’index pour commencer au début du tableau à chaque tour.

```
while ["$index" -lt "$comparaisons"] # Début de la boucle interne.
do
  if [${tab[$index]} \> ${tab[`expr $index + 1`]} ] # Si non ordonné...
  then
    echange $index `expr $index + 1` # échange.
  fi
  let "index += 1" # Ou index+=1 sur Bash 3.1 et suivants
done # Fin de la boucle interne.
let "comparaisons -= 1" # retranche une comparaison (effectuée)
let "index += 1" # Incrémente le compteur de tour.

```

done # Fin de la boucle externe.  
echo “${tab[@]}”; return; # “renvoie” le tableau trié  
}  
[/code]

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Février 20, 2016, 5:29 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/10 "2016-02-20T17:29:58Z")

</div>

Appeler une fonction en passant le contenu d’un tableau n’était pas l’objectif.

De plus, passer, comme tu le fais, le contenu d’un tableau dont un ou plusieurs éléments comportent des espaces pose problème. Passer le contenu du tableau (‘rouge’ ‘gris clair’ ‘vert’) tout en préservant l’espace de gris clair n’est pas si évident. Tu vas devoir jongler avec IFS. Enfin, si tu utilises, comme tu le fais, les paramètres positionnels $1 $2 etc… pour passer le contenu d’un tableau, comment feras-tu pour passer plusieurs tableaux à une fonction?

```auto

```

Le passage de tableau par référence est la seule solution. Même si, je le répète, il s’agit plus d’un exercice de style qu’autre chose car il existe des langages plus puissants pour ce genre de choses: perl, python, php etc… Et dans ce genre d’exercice de style, bash est lourd!

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 5:30 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/11 "2016-02-20T17:30:02Z")

</div>

> [@](#):
>
> Le passage de tableau par référence est la seule solution. Même si, je le répète, il s’agit plus d’un exercice de style qu’autre chose car il existe des langages plus puissants pour ce genre de choses: perl, python, php etc… Et dans ce genre d’exercice de style, bash est lourd!

Signification : c’est de la pure masturbation intelectuelle.

Mais certains font pire! Il programment des shell comme zsh avec des histoires d’espaces de nom, de module à importer, intégrer ncurse en natif au script shell,… 😮

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Février 20, 2016, 5:30 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/12 "2016-02-20T17:30:02Z")

</div>

[quote=“MisterFreez”]Signification : c’est de la pure masturbation intelectuelle.

Mais certains font pire! Il programment des shell comme zsh avec des histoires d’espaces de nom, de module à importer, intégrer ncurse en natif au script shell,… 😮[/quote]

Ouaip! Il ne nous reste plus qu’à nous inscrire à l’Obfuscated Code Contest ![:smt030](https://www.debian-fr.org/uploads/default/original/1X/65b1b73704eec538091c0e1d04a633b3840a284f.gif)  
[en.wikipedia.org/wiki/Obfuscated\_code](http://en.wikipedia.org/wiki/Obfuscated_code)

Pas tout à fait inutile quand même. Les scripts shell sont encore fort utilisés et certains sont fort complexes. Il suffit de se balader dans /etc/init.d/ pour s’en convaincre.

---

<div class="post-metadata">

**Author:** ![usinagaz](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/u/ecae2f/32.png) [@usinagaz](https://www.debian-fr.org/u/usinagaz)\
**Post date:** [Février 20, 2016, 5:30 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/13 "2016-02-20T17:30:02Z")

</div>

Oui, et c’est trés bien ce que tu as fait. Rien d’autre à faire à mon avis aussi.  
Mais je ne sais pas si on parle à juste titre de référence passée …  
Une référence indirecte, c’est ni plus ni moins qu’une évaluation, {!tab\_str},  
c’est un peu `eval` non , d’un littéral qui a un sens ?

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 5:30 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/14 "2016-02-20T17:30:03Z")

</div>

> [@](#):
>
> Pas tout à fait inutile quand même. Les scripts shell sont encore fort utilisés et certains sont fort complexes. Il suffit de se balader dans /etc/init.d/ pour s’en convaincre.

Je dis pas le contraire je dis que d’une manière générale vouloir tout faire avec un langage c’est se voiler la face et que chercher à recoder linux en \*sh c’est vouer à l’écheque.

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Février 20, 2016, 5:30 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/15 "2016-02-20T17:30:04Z")

</div>

[quote=“usinagaz”]Mais je ne sais pas si on parle à juste titre de référence passée …  
Une référence indirecte, c’est ni plus ni moins qu’une évaluation, {!tab\_str},  
c’est un peu `eval` non , d’un littéral qui a un sens ?[/quote]

Il s’agit vraiment de passage par référence car le tableau de départ est modifié si on modifie son nameref dans la fonction. Je parle de ksh. Pour bash, je n’ai pas testé. Trop confus comme solution.

> [@](#):
>
> Je dis pas le contraire je dis que d’une manière générale vouloir tout faire avec un langage c’est se voiler la face et que chercher à recoder linux en \*sh c’est vouer à l’écheque.

Les chèques en bois? 😉

C’est bien pourquoi j’appelle ça un exercice de style. Ce n’est rien d’autre que ça. Sans doute pour les mêmes raisons que celles qui te font préférer zsh. Parce qu’entre-nous, les nouvelles fonctionnalités de zsh, n’ont pas plus de raisons d’être que les nameref (références indirectes) de ksh. Elles facilitent la vie du “scripteur” sans plus. Tu n’as pas choisi zsh pour recoder linux non plus je présume? 😉

---

<div class="post-metadata">

**Author:** ![MisterFreez](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/m/bb73d2/32.png) [@MisterFreez](https://www.debian-fr.org/u/MisterFreez)\
**Post date:** [Février 20, 2016, 5:30 UTC](https://www.debian-fr.org/t/shell-passage-dun-tableau-a-une-fonction/13282/16 "2016-02-20T17:30:08Z")

</div>

> [@](#):
>
> C’est bien pourquoi j’appelle ça un exercice de style. Ce n’est rien d’autre que ça. Sans doute pour les mêmes raisons que celles qui te font préférer zsh. Parce qu’entre-nous, les nouvelles fonctionnalités de zsh, n’ont pas plus de raisons d’être que les nameref (références indirectes) de ksh. Elles facilitent la vie du “scripteur” sans plus. Tu n’as pas choisi zsh pour recoder linux non plus je présume? 😉

J’ai codé 2 ou 3 trucs avec zsh pour voir les différences.

99,9% de mes scripts shell sont posix (modulo les programmes lancés en plus).
