# Problème boucle infinie

**URL:** <https://www.debian-fr.org/t/probleme-boucle-infinie/65452>\
**Category:** Programmation\
**Created:** [Février 21, 2016, 9:29 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452 "2016-02-21T21:29:59Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![tartenpion95](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/t/bbe5ce/32.png) [@tartenpion95](https://www.debian-fr.org/u/tartenpion95)\
**Post date:** [Février 21, 2016, 9:29 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/1 "2016-02-21T21:29:59Z")

</div>

Bonjour,

J’ai créé un script qui demande à l’utilisateur d’entrée une adresse IP en vue de la modifié automatiquement dans des fichiers. Les tests sur l’adresse IP fonctionne mais le script est infini.

Voici le code:

```auto

#!/bin/sh

#Déclaration variables

TEST_IP=false

#question utilisateur

#IP 
while ["TEST_IP" != "true"]
	do echo "Entrer l'IP du serveur"
	read IP
		oldIFS=$IFS
		IFS=.
		set -- $IP
			if ["$#" -ne "4"]; then
				echo "L'IP doit avoir 4 blocs"
			else
				for oct in $1 $2 $3 $4; do
					echo $oct | egrep "^[0-9]+$" >/dev/null 2>&1
					if ["$?" -ne "0"] || ["$oct" -lt "0" -o "$oct" -gt "255"]; then
						echo "$oct: IP incorrect"
					else
						TEST_IP=true
					fi
				done
			fi
	done
done

```

Cela ne doit pas etre grand chose mais je ne suis pas un expert en dev.

Merci

Cordialement

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 9:29 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/2 "2016-02-21T21:29:59Z")

</div>

A tout hasard, vérifie le nom de la variable que tu testes dans ton while.

PS : ce genre de question est plutôt pour le forum programmation.

---

<div class="post-metadata">

**Author:** ![tartenpion95](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/t/bbe5ce/32.png) [@tartenpion95](https://www.debian-fr.org/u/tartenpion95)\
**Post date:** [Février 21, 2016, 9:29 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/3 "2016-02-21T21:29:59Z")

</div>

le nom de la variable est bonne.

Pardon d’avoir posté au mauvais endroit

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 9:29 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/4 "2016-02-21T21:29:59Z")

</div>

> [@tartenpion95](#):
>
> le nom de la variable est bonne.

Si tu le dis. Dans ce cas il faut entrer «&nbsp;true&nbsp;» à l’invite pour que la boucle s’arrête.  
Mais alors je ne vois pas bien à quoi sert la variable TEST\_IP.

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 9:29 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/5 "2016-02-21T21:29:59Z")

</div>

Tu as édité ton message mais tu as mal corrigé, il manque le $.

Pour le reste,

- il y a un done en trop à la fin ;
- le test de validité de l’adresse IP est insuffisant : il lui suffit qu’un octet soit bon pour que l’adresse soit considérée comme bonne.

---

<div class="post-metadata">

**Author:** ![vohu](https://www.debian-fr.org/user_avatar/www.debian-fr.org/vohu/32/4108_2.png) [@vohu](https://www.debian-fr.org/u/vohu)\
**Post date:** [Février 21, 2016, 9:30 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/6 "2016-02-21T21:30:17Z")

</div>

En général, lorsqu’on a une boucle infinie il faut verifier que :

- la condition de sortie de la boucle est possible.
- le code contenu dans la boucle peut un jour modifier la condition de sortie

Donc on verifie le premier cas :

```auto

```

Bingo : 2 chaines de caractères ne peuvent pas êtres égales…

En bash, lorsqu’on veut utiliser le contenu d’une variable, il faut utiliser $ ou $(mavar)  
Essaye avec “$TEST\_IP”

il n’y a pas de quotes autour de true (c’est un mot clef ayant une valeur) :

```auto

```

il y a un done en trop en bas. while…do sont ensembles

Le code fonctionnel :

```auto
#!/bin/sh

#Déclaration variables

TEST_IP=false

#question utilisateur

#IP
while ["$TEST_IP" != true]
do echo "Entrer l'IP du serveur"
  read IP
  oldIFS=$IFS
  IFS=.
  set -- $IP
    if ["$#" -ne "4"]; then
      echo "L'IP doit avoir 4 blocs"
    else
      for oct in $1 $2 $3 $4; do
        echo $oct | egrep "^[0-9]+$" >/dev/null 2>&1
        if ["$?" -ne "0"] || ["$oct" -lt "0" -o "$oct" -gt "255"]; then
          echo "$oct: IP incorrect"
        else
          TEST_IP=true
        fi
      done
    fi
done
```

---

<div class="post-metadata">

**Author:** ![PascalHambourg](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pascalhambourg/32/5837_2.png) [@PascalHambourg](https://www.debian-fr.org/u/PascalHambourg)\
**Post date:** [Février 21, 2016, 9:30 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/7 "2016-02-21T21:30:17Z")

</div>

> [@vohu](#):
>
> il n’y a pas de quotes autour de true (c’est un mot clef ayant une valeur)

Les guillemets autour de «&nbsp;true&nbsp;» sont inutiles, mais dans le contexte de l’expression conditionnelle entre crochets et de l’affectation de variable, «&nbsp;true&nbsp;» est bien une simple chaîne de caractères et non un mot-clé ou une commande.

---

<div class="post-metadata">

**Author:** ![PengouinPdt](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pengouinpdt/32/3978_2.png) [@PengouinPdt](https://www.debian-fr.org/u/PengouinPdt)\
**Post date:** [Février 21, 2016, 9:43 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/8 "2016-02-21T21:43:37Z")

</div>

Bien que le shell comprenne les notions booléennes, une variable shell est true si elle a une valeur affectée, sinon elle est false.  
En écrivant TEST\_IP=false, tu lui affecte une valeur - de type string, par défaut, si je ne me trompe pas -, elle est donc vraie !

Dans ta boucle while, tu cherches à vérifier que la valeur affectée à la variable TEST\_IP, soit bien une chaîne de caractères nommée «&nbsp;true&nbsp;» …  
Ce n’est en rien un booléen !  
- Là, est souvent l’erreur de raisonnement, en shell, ce n’est pas parce que tu écris une variable=true que cela en fait un booléen True … ce n’est pas l’usage du mot «&nbsp;true&nbsp;» qui en fait un booléen ; variable=false est aussi positionné comme étant vrai !  
Dans les deux cas, tu déclares une variable de type string, elles ont de fait pour valeur booléenne, vraie …  
Pour qu’une variable soit de valeur booléenne false, il faut simplement la déclarer ainsi : ‹&nbsp;nomvariable&nbsp;› sans aucune affectation de valeur … dans ce cas, et seulement ce cas, elle est de type booléen false … 😉

Dans ce genre de test, il vaut mieux utiliser des valeurs de type entier, type 0 et 1, car vraiment plus simple à gérer … par le biais de la déclaration ‹&nbsp;typeset -i&nbsp;› (ou en bash ‹&nbsp;declare -i&nbsp;›) … - autrement cela reviendrait à affecter à ta variable, un caractère de forme 0 ou 1 et non pas l’entier 0 ou 1, ainsi le test correct serait d’utiliser les opérateurs pour chaîne de caractères, et non pas pour entier …

Ton test while deviendrait ainsi - parce qu’on chercherait à tester que la variable TEST\_IP soit de type booléen vrai - :

```auto
while ["$TEST_IP"] ...
```

Hors cette écriture est exactement l’équivalent de :

```auto
while true ... 
```

ou sa variante :

```auto
while : ... 
```

Ensuite, ton code est faux, parce qu’en fait, tu sors de ta boucle for, mais jamais de ta boucle while !

Ainsi, ton code corrigé est :

```auto
typeset -i TEST_IP=0
oldIFS=$IFS
#question utilisateur
while :
do echo "Entrer l'IP du serveur"
    read IP

    IFS=.
    set -- $IP
    if ["$#" -ne 4]; then
        echo "L'IP doit avoir 4 blocs"
    else
        for oct in "$@"; do
            echo "$oct" | grep -P "^[0-9]+$" >/dev/null 2>&1

            if ["$?" -ne 0] || ["$oct" -lt 0 -o "$oct" -gt 255]; then
                echo "$oct: IP incorrect"
                TEST_IP=1
            fi
        done
        if ["$TEST_IP" -eq 0]; then
            IFS="$oldIFS"
            break
        else
            TEST_IP=0
        fi
    fi
done
```

Résultat :

> [@](#):
>
> user@ptb:~/Documents/Programmation$ ./test  
> Entrer l’IP du serveur  
> 1.1.1.1
> 
> user@ptb:~/Documents/Programmation$ ./test  
> Entrer l’IP du serveur  
> 1.2.3.4.5  
> L’IP doit avoir 4 blocs  
> Entrer l’IP du serveur  
> a.2.3.4  
> a: IP incorrect  
> Entrer l’IP du serveur  
> 5.6.7.8

Remarques :

- si l’usage de la déclaration ‹&nbsp;typeset -i&nbsp;› ne fonctionne pas, tu peux écrire ainsi : i[/i] … de même certains shell acceptent l’usage de la commande mathématique ‹&nbsp;let&nbsp;›, tel que : ‹&nbsp;let TEST\_IP=0&nbsp;› … pfff !
- la variable oldIFS doit être hors de ta boucle while, sinon tu la réinitialise à chaque fois - pour RIEN -… d’autant que tu ne réinitialises jamais dans ton code IFS … que ce soit quand tu sors de ta boucle for et/ou de ta boucle while !
- Un autre point est concernant l’usage du pattern de recherche pour ton grep (ou egrep), utilises l’option -P …
- l’usage de ‹&nbsp;set – $IP&nbsp;› n’est pas conforme, car normalement, il faudrait quoter «&nbsp;$IP&nbsp;» … néanmoins, dans l’immédiat, cela casse le code …
- tu remarqueras aussi la modification de la boucle for, par l’usage du paramètre positionnel «&nbsp;$@&nbsp;» : en effet, puisqu’auparavant tu détectes le nombre de paramètres, autant utiliser ce paramètre positionnel plutôt que tes 4 déclarations de paramètres $1 à $4 …
- dernier point, je te laisse comprendre l’usage du test conditionnel final sur TEST\_IP et surtout l’usage du ‹&nbsp;else&nbsp;› … test en le supprimant / commentant 😉

Voili, voilou …

---

<div class="post-metadata">

**Author:** ![PengouinPdt](https://www.debian-fr.org/user_avatar/www.debian-fr.org/pengouinpdt/32/3978_2.png) [@PengouinPdt](https://www.debian-fr.org/u/PengouinPdt)\
**Post date:** [Février 21, 2016, 9:43 UTC](https://www.debian-fr.org/t/probleme-boucle-infinie/65452/9 "2016-02-21T21:43:38Z")

</div>

Voici le code modifié, pour illustrer le fonctionnement booléen :

```auto
set TEST_IP # declaration de la variable sans aucune affection de valeur !
oldIFS=$IFS
#question utilisateur
while :
do echo "Entrer l'IP du serveur"
    read IP

    IFS=.
    set -- $IP
    if ["$#" -ne 4]; then
        echo "L'IP doit avoir 4 blocs"
    else
        for oct in "$@"; do
            echo "$oct" | grep -P "^[0-9]+$" >/dev/null 2>&1

            if ["$?" -ne 0] || ["$oct" -lt 0 -o "$oct" -gt 255]; then
                echo "$oct: IP incorrect"
                TEST_IP=nimportequoicommevaleur # n'importe quelle valeur est acceptée : '0', 0, tout symbole ... la variable existe, donc elle est vraie
            fi
        done

        if ["$TEST_IP"]; then # équivalent de : if test -n "$TEST_IP" ... ou de if [-n "$TEST_IP"]
            unset TEST_IP
        else
            IFS="$oldIFS"
            break
        fi
    fi
done
```

😃 😉
