75 votes

Comment fonctionnent SETLOCAL et ENABLEDELAYEDEXPANSION ?

J'ai remarqué que dans la plupart des scripts, les deux sont généralement dans la même ligne ainsi :

SETLOCAL ENABLEDELAYEDEXPANSION

Ces deux commandes sont-elles en fait distinctes et peuvent-elles être écrites sur des lignes séparées ?

Fixation de la volonté ENABLEDELAYEDEXPANSION a un effet négatif sur un script s'il est défini sur les premières lignes du script et n'est pas désactivé avant la fin du script ?

141voto

Michel de Ruiter Points 1326

Je pense que vous devriez comprendre ce qu'est l'expansion retardée est . Les réponses existantes ne l'expliquent pas (suffisamment), à mon avis.

Dactylographie SET /? explique la chose raisonnablement bien :

L'expansion retardée des variables d'environnement est utile pour contourner les limitations de l'expansion actuelle qui se produit lorsqu'une ligne de ligne de texte est lue, et non lorsqu'elle est exécutée. L'exemple suivant démontre le problème de l'expansion immédiate des variables :

set VAR=before
if "%VAR%" == "before" (
    set VAR=after
    if "%VAR%" == "after" @echo If you see this, it worked
)

n'afficherait jamais le message, puisque le %VAR% dans les DEUX instructions IF est substituée lorsque la première instruction IF est lue, puisqu'elle inclut logiquement inclut le corps de l'instruction IF, qui est une instruction composée. Ainsi, l'instruction IF à l'intérieur de l'instruction composée compare réellement "avant" avec "après", qui ne seront jamais égaux. De même, l'exemple suivant ne fonctionnera pas comme prévu :

set LIST=
for %i in (*) do set LIST=%LIST% %i
echo %LIST%

en ce sens qu'il ne construira PAS une liste de fichiers dans le répertoire courant, mais se contentera de mettre la variable LIST sur le dernier fichier trouvé. Encore une fois, cela est dû au fait que la %LIST% n'est développée qu'une seule fois lorsque l'instruction FOR est lue, et à ce moment-là, la variable LIST est vide. Ainsi, la boucle FOR que nous exécutons est donc la suivante

for %i in (*) do set LIST= %i

qui ne fait que mettre LIST sur le dernier fichier trouvé.

L'expansion retardée de la variable d'environnement vous permet d'utiliser un différent différent (le point d'exclamation) pour développer les variables d'environnement au d'environnement au moment de l'exécution. Si l'expansion retardée des variables est activée, les exemples ci-dessus exemples ci-dessus pourraient être écrits comme suit pour fonctionner comme prévu :

set VAR=before
if "%VAR%" == "before" (
    set VAR=after
    if "!VAR!" == "after" @echo If you see this, it worked
)

set LIST=
for %i in (*) do set LIST=!LIST! %i
echo %LIST%

Un autre exemple est ce fichier batch :

@echo off
setlocal enabledelayedexpansion
set b=z1
for %%a in (x1 y1) do (
 set b=%%a
 echo !b:1=2!
)

Cette impression x2 y y2 : chaque 1 est remplacé par un 2.

Sans setlocal enabledelayedexpansion Les points d'exclamation ne sont que cela, donc il y aura un écho. !b:1=2! deux fois.

Parce que les variables d'environnement normales sont développées lorsqu'une instruction (de bloc) est lire en expansion %b:1=2% utilise la valeur b a avant la boucle : z2 (mais y2 lorsqu'il n'est pas défini).

12voto

Aacini Points 19316

La partie ENABLEDELAYEDEXPANSION est OBLIGATOIRE dans certains programmes qui utilisent l'expansion retardée, c'est-à-dire qui prend la valeur des variables qui ont été modifiées à l'intérieur des commandes IF ou FOR en entourant leurs noms de points d'exclamation.

Si vous activez cette expansion dans un script qui ne le nécessite pas, le script se comporte différemment uniquement s'il contient des noms enfermés dans des points d'exclamation !LIKE ! !THESE ! Habituellement, le nom est simplement effacé, mais si une variable avec le même nom existe par hasard, alors le résultat est imprévisible et dépend de la valeur de cette variable et de l'endroit où elle apparaît.

La partie SETLOCAL est OBLIGATOIRE dans quelques programmes spécialisés (récursifs) seulement, mais elle est couramment utilisée lorsque vous voulez être sûr de ne pas modifier par hasard une variable existante portant le même nom ou si vous voulez supprimer automatiquement toutes les variables utilisées dans votre programme. Toutefois, comme il n'existe pas de commande distincte pour activer l'expansion différée, les programmes qui l'exigent doivent également inclure la partie SETLOCAL.

1voto

Rob Points 9

Un véritable problème se pose souvent, car toutes les variables définies à l'intérieur ne seront pas exportées lorsque ce fichier batch se terminera. Il n'est donc pas possible d'exporter, ce qui nous a causé des problèmes. En conséquence, j'ai simplement configuré le registre pour qu'il utilise TOUJOURS l'expansion différée (je ne sais pas pourquoi ce n'est pas la valeur par défaut, cela pourrait être une question de vitesse ou de compatibilité héritée).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X