• 4 heures
  • Facile

Mis à jour le 30/01/2018

L'expansion retardée

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

L'expansion retardée est un des concepts les plus avancés de Batch et de loin le plus dur à expliquer.

Pour bien le comprendre, nous allons tout d'abord passer en revue certains points de base mineurs que nous n'avons pas évoqué au début du tutoriel de peur d'embrouiller ou de décourager les lecteurs.

Les instructions

Dans l'introduction au tutoriel, j'ai écrit que Batch permettait d'exécuter une suite d'instructions et nous nous en sommes contenté depuis le début.

De fait, nous avons pu examiner des commandes depuis le tutoriel qui ressemblaient à ça :

echo Salut

En allant plus loin, on découvre qu'il existe aussi des instructions combinées, soit des plusieurs instructions en une seule ligne, qui sont séparées par le signe ‹ & ›.

echo Hello & echo World

Jusque là, rien de compliqué. La difficulté que nous allons résoudre avec l'expansion retardée est posée par les blocs de codes. Ils sont délimités par des parenthèses et ressemblent à ça :

(echo Hello
echo World)

Ceci va permettre aux instructions d'être "préprocessé" en même temps. Vous n'avez rien compris ? Pas de panique, dans 15 minutes vous vous sentirez beaucoup mieux et aurez une bien meilleure vision de Batch.

Au coeur de Batch

Au début du tutoriel, nous avons parlé du fait que CMD exécutait les commandes. En réalité, deux entités se partagent ce travail, que l'on appelle le préprocesseur et le processeur.

Prenons l'exemple de ce code :

set vari=0
if %vari%==0
(
  echo vari est égale à 0.
)

Le préprocesseur lit la ligne 1. Il n'y trouve rien d'intéressant et le retour à la ligne lui indique que c'est la fin de l'instruction.  Il l'envoie donc au processeur pour que celui-ci exécute l'action et crée une variable vari et lui donner comme valeur 0.

Le préprocesseur lit la ligne 2. Il voit %vari%. Pour faciliter la tâche au processeur, il change %vari% par sa valeur, c'est-à-dire 0. Il voit la fin de ligne et envoie l'instruction au processeur. Le processeur recevra donc if 0==0 comme instruction et l'exécutera.

Le préprocesseur voit ensuite un parenthésage. Il va donc traiter les données et les envoyer au processeur toutes à la fois, donc aucune action ne sera executé avant que tout ai été préprocessé.

Le problème

Prenons désormais ce code :

set a=0
if %a%==0 ( 
  set a=1
  echo %a%
)

Je vous laisse 30 secondes pour deviner le problème.

Difficile, hein ?

Analysons donc ce code.

Ligne 1 : Le préprocesseur ne vois rien de spécial, l'envoie au processeur qui va exécuter l'action et donner comme valeure 0 à a.

Ligne 2 : Le préprocesseur remplace le %a% par 0, envoie ca au processeur qui évalue la condition.

Ligne 3 et 4 : Même dans un if, les parenthèses forment un bloc. Le préprocesseur va donc voir set a=1, puis regarder la ligne d'après sans envoyer l'action au processeur. A ce point-là, a est donc toujours égal à 0. Le processeur voit %a%, et malheur : il le remplace par 0. Le préprocesseur détecte la fermeture de parenthèse, et envoie le code au processeur. Le processeur exécute la première ligne, et change la valeur de a de 0 vers 1. Ensuite, il voit la commande "echo 0", et écrit 0.  Bien évidemment, si l'on avait ajouté un echo après la fermeture de parenthèse du if, on aurait eu 1, car l'action de changement de la valeur aurait été exécutée.

C'est bien gentil les problèmes, mais les solutions, c'est mieux, alors allons-y ! :)

La solution

Nous voilà enfin a parler de l'expansion retardée.

L'expansion retardée demande au préprocesseur de ne pas remplacer la variable par sa valeur.

Pour pouvoir l'utiliser, il est nécessaire d'ajouter au début de son code

setlocal enableDelayedExpansion

Pour ceci, on utilisera donc des points d'exclamations au lieu de signe modulo.

Notre code ressemble donc à celui ci:

setlocal enableDelayedExpansion
@echo off
set a=0
if %a%==0 ( 
set a=1
echo !a!
 )

Et voilà, on lance le programme : il affiche bien 1 :) !

La compréhension de ce chapitre n'est pas simple, donc bravo à vous si vous en êtes arrivés ici ;) .

Exemple de certificat de réussite
Exemple de certificat de réussite