# [BASH] Portée d'une variable
[BASH] Portée d'une variable

## Elrond_2031

Bonjour

J'ai un problème avec la gestion des variables en bash.

Je ne comprend pas pourquoi dans l'exemple ci-dessous, il n'y

a qu'une ligne vide qui s'affiche

```

#!/bin/bash

  

function toto ()

{

   R="3"

}

function titi()

{

   echo "i" | toto

   echo $R

}

titi

```

Si quelqu'un pouvait m'éclairer?

----------

## theturtle123

heu déjà il me semble que ce n'est pas la bonne manière d'appeller ta fonction...

il faudrait l'appeller avec 

```
toto $î
```

en effet une fonction bash s'appelle comme une commande shell classique et tu accèdes aux arguents avec $1...$9...

après ça devrait mieux marcher déjà   :Wink:  [/code]

EDIT : hahaha je me suis emballé, c'est la fatigue... j'avais mal lu ton post ça serait plutot

```
toto "i"
```

quoique ta version devrait fonctionner aussi...

teste toujours

sinon ça devrait marcher   :Twisted Evil: 

encore désolé pour ce post débileLast edited by theturtle123 on Thu Jun 10, 2004 9:45 pm; edited 1 time in total

----------

## Elrond_2031

non non, c'est bien comme ca que je veux appeler ma fonction.

En effet, ici j'ai simplifier,  mais la vrai fonction toto lit des choses sur son entrée standard

je sais que si j'avais fais

```

#!/bin/bash

 

function toto ()

{

   R="3"

}

function titi()

{

   toto

   echo $R

}

titi

```

ca aurait fonctionner.

Je comprend pas pourquoi dans ce cas ca marche, est dans le cas d'un pipe ca ne marche pas.

Pourquoi dans un cas la variable "R" est disponible au retour de la fonction toto mais pas dans l'autre.

Mais merci

Une autre idée?

----------

## Angelion

Ahhhhh, les entrailles de bash   :Wink: 

il semblerait que l'hors d'un pipe ,  la fonction ne soit pas interpretée sous le meme contexte, et donc pas d'assignement de variable accessible depuis ton script, a son retour.

dans le shel si tu tapes par ex: ls | R=3 , R n'est pas defini au retour.

----------

## julienm

Il y a un truc que je pige pas, pourquoi est-ce que tu relies  la commande 'echo "i" ' à ta commande toto puisque celle-ci ne filtre rien du tout?

Mais à part ça, j'ai essaayé ta fonction et elle m'affiche 3 ( les variables sont globales en bash sauf si elles sont précédées du mot clef "local").

----------

## fafounet

Je pense qu'il faudrait simplement que tu lises de la documentations sur l'utilisation des pipes.

Je te dirai bien man bash mais je pense que sur google un "tutorial bash pipe" est plus simple

----------

## Angelion

il a mis echo "i" comme il aurait pu mettre "ls" , c'etait juste pour faire un pipe apres

----------

## BobDylan

Ben peut-être paske tu ne peux pas piper sur l'entrée standard d'une fonction qui ne fait que renvoyer la valeur d'une variable définie localement.

Tu devrais d'abord voir du coté des tutoriels   :Wink: 

Voici des liens qui peuvent t'intéresser:

Pipes, jokers et redirections

Advanced Bash Scripting Guide

Sinon, si tu nous dis ce que tu veux faire avec ton script, on peut peut-être te filer des tuyaux.

----------

## fafounet

Il existe une traduction francaise du ABS 

http://abs.ptithibou.org/abs-2.3-fr/

----------

## TGL

 *BobDylan wrote:*   

> Ben peut-être paske tu ne peux pas piper sur l'entrée standard d'une fonction qui ne fait que renvoyer la valeur d'une variable définie localement.

 

Stoooop. La bonne réponse a été donnée plusieurs posts plus haut par Angelion : chaque portion d'un pipe est executée dans un sous-shell, et donc les affectations de variable qui s'y trouvent n'ont aucun effet sur le programme principal. 

Donc quand on a vraiment besoin de remonter de l'info depuis un pipe vers le programme, on utilise les E/S standards à la place. Pour son exemple, la solution standard serait : 

```
#!/bin/bash

 

function toto ()

{

   echo "3"

}

function titi()

{

   R=$(echo "i" | toto)

   echo $R

}

titi
```

Cf. la FAQ de Bash, question E4 :

http://www.faqs.org/faqs/unix-faq/shell/bash/

----------

## Elrond_2031

Merci pour toute vos réponse.

TGL -> j'ai déjà utilisé ca, mais dans mon cas ca ne m'arrange pas   :Sad:   parce que pour compliquer le tout toto affiche déjà des choses dans la sortie standard :/

Maintenant que j'ai une explication de pourquoi ca marche pas, je vais essayer de repenser autrement mon script  :Rolling Eyes: 

Mais je vais d'abord aller voir vos lien  :Wink: 

----------

## Elrond_2031

pour info voila la vrai fonction toto

```

# param $1 : the indice of the graph

# param $2 : the indice of the curve

# param $3 : the type of the curve

function render_point()

{

  echo "@target G$1.S$2"

  echo "@type $3"

  max="0"

  while read ligne

  do

    ligne="$ligne FIN"

    nb=`head $ligne`

    ligne=`tail $ligne`

    h=`head $ligne`

    while [ $h != "FIN" ]

    do

      echo "$nb $h"

      max=`max $max $h`

      ligne=`tail $ligne`

      h=`head $ligne`

    done

  done

  echo "&"

  RET="$max"

}

```

et j'aurai voulus que l'appelant récupère la valeur de $max (mais sans écrire sur la sortie standard)

----------

## Sleeper

Et 

```

# param $1 : the indice of the graph

# param $2 : the indice of the curve

# param $3 : the type of the curve

function render_point()

{

  echo "@target G$1.S$2"

  echo "@type $3"

  max="0"

  while read ligne

  do

    ligne="$ligne FIN"

    nb=`head $ligne`

    ligne=`tail $ligne`

    h=`head $ligne`

    while [ $h != "FIN" ]

    do

      echo "$nb $h"

      max=`max $max $h`

      ligne=`tail $ligne`

      h=`head $ligne`

    done

  done

  echo "&"

  return $max

} 

cat file | render_point

R=$?

```

Ca le fait pas ?

----------

## Angelion

Une soluce possible, tu vires le pipe, et tu lis une variable globale ou un fichier, je ne sais pas ce que c'est, et là tu pourras avoir acces a $max.

Perso, si c un projet qui ne requiert pas forcement bash, je le ferai en Perl   :Wink: 

----------

## Elrond_2031

Faudra que j'apprenne le perl un jour, quand j'aurai le temps...   :Wink: 

en attendant, je vais surement utiliser un fichier temporaire  :Wink: 

----------

## Angelion

Personellement je trouve qu'on apprend bien plus vite a maitriser Perl que les scripts Bash.

Bon, ok, je code en C depuis plusieurs années, ca aide ...

----------

## Sleeper

Enfin, bon dans ce cas precis, il suffit de recuperer la valeur de retour de la fonction ...  L'exemple que je t'ai donne devrait le faire ...

Neammoins c'est quand meme bien d'apprendre le Perl .. et le Ruby  :Wink: 

----------

## TGL

 *Elrond_2031 wrote:*   

> TGL -> j'ai déjà utilisé ca, mais dans mon cas ca ne m'arrange pas    parce que pour compliquer le tout toto affiche déjà des choses dans la sortie standard :/

 

Tu peux utiliser d'autres sorties alors. Par défaut, bash bosse avec 2 descripteurs de fichiers, mais rien n'empêche d'en utiliser plus. Par exemple :

```

function render_point()

{

  [...]

  # la sortie du résultat se fait sur fd3 :

  echo "$max" >&3

} 

# Pour lire le résultat, on redirige temporairement fd3 sur fd1.

# Mais du coup, pour pas mélanger avec la sortie standard 

# du sous shell (les affichages de la fonction), on doit 

# temporairement renvoyer cette dernière sur un autre 

# descripteur (fd4), qui sera lié finallement à la sortie 

# standard principale, histoire de remettre les choses en 

# ordre.

{ RES="$(cat file | render_point 3>&1 1>&4)" } 4>&1

```

(disclaimer: pas testé...)

Mais sinon, c'est vrai que le code de retour de la fonction, pour rendre un entier, ça peu le faire. Sauf si on veut garder ce code pour la gestion d'erreurs biensûr.

À part ça, ++ pour l'idée d'apprendre un langage plus évolué que le bash, c'est vraiment agréable au quotidien. Apprends perl, ruby ou python, comme tu veux (question de goût, pas troller, tout ça...), mais apprends en un.

----------

## Sleeper

 *TGL wrote:*   

>  Apprends perl, ruby ou python, comme tu veux (question de goût, pas troller, tout ça...), mais apprends en un.

 

Arghhh ... ne me tente pas  :Wink: 

----------

## Elrond_2031

merci TGL, ca doit surement être la solution.

Mais en attendant je testerais surement plus tard, là la solution du fichier temporaire me convient pour le moment (et j'ai pas le temps de tout rechanger)

----------

