web-dev-qa-db-fra.com

Exemple d'extension retardée dans un fichier batch

Quelqu'un peut-il me donner un exemple où un script batch agirait différemment avec ou sans expansion retardée? Y a-t-il des situations où vous ne voudriez PAS utiliser l'expansion retardée? Merci.

42
Neil Weicher

Regardez les exemples suivants ...

Exemple 1: Le code suivant N'UTILISE PAS l'expansion retardée, donc les variables de la boucle for ne sont développées qu'une seule fois. Cela signifie que %Count% sera toujours étendu à 0 à chaque itération de la boucle, peu importe ce que nous lui faisons avec la commande set:

@echo off
set COUNT=0

for %%v in (1 2 3 4) do (
  set /A COUNT=%COUNT% + 1
  echo Count = %COUNT%
)
pause

Donc, ce script affichera:

Count = 0
Count = 0
Count = 0
Count = 0

Ce n'est pas ainsi que cette boucle est censée fonctionner.

Exemple 2: D'autre part, si nous utilisons une expansion retardée, nous avons le script suivant, qui s'exécutera comme prévu.

setlocal ENABLEDELAYEDEXPANSION
set COUNT=0

for %%v in (1 2 3 4) do (
  set /A COUNT=!COUNT! + 1
  echo Count = !COUNT!
)

pause

et, comme prévu, il affichera:

Count = 1
Count = 2
Count = 3
Count = 4

Lorsque vous utilisez ENABLEDELAYEDEXPANSION et développez une variable à l'aide de ! au lieu de %, la variable est re-développée à chaque fois, et tout fonctionne comme prévu.

56
Max

Je voulais ajouter un excellent exemple sur la façon dont "EnableDelayedExpansion" (EDE) peut être utile en dehors des exemples de boucle FOR omniprésents.

Voici une ligne de données sismiques que je souhaite analyser (je l'appelle 1line.txt)

ak_11574812 2015.04.29.193822 62.9525 -148.8849 1.0 9.5 1 49 km S de Cantwell, Alaska

Le problème que j'ai rencontré était que le dernier segment de cette ligne ne démarre pas toujours au même numéro de colonne. J'ai donc dû créer une commande SET flexible qui arrachera avec précision le dernier segment de cette ligne.

ECHO OFF
setlocal enableDelayedExpansion
set where=72
set /p line=<1line.txt
set locate=!line:~%where%,28!
echo %locate%

EDE me permet de placer une variable (où) à l'intérieur d'une autre variable (ligne). EDE traduira d'abord la variable entre crochets par%, puis traitera la variable entre crochets par! et (dans ce cas) Poussez les résultats dans la variable "Locate".

9
Bruce Sinkula

réponse de Max donne un exemple de cas où un script batch agirait différemment avec ou sans expansion retardée.

Par souci d'exhaustivité, répondons à une autre partie de la question et montrons une situation où vous ne voudriez PAS utiliser l'expansion retardée lorsque vos données contiennent une exclamation marque ! (et montrer deux façons de traiter ces données):

@ECHO OFF
SETLOCAL EnableExtensions DisableDelayedExpansion

  set "_auxFile=%temp%\%~n0.txt"
  rem create multiline sample file
  >"%_auxFile%" ( for /L %%G in (1,1,3) do echo line %%G is 100%% valid! Sure! Hurrah!)
  rem create one-line sample file
  >"%_auxFile%" echo this line is 100%% valid! Sure! Hurrah!

  echo(
  echo --- file content 
  type "%_auxFile%"

  echo(
  SETLOCAL EnableDelayedExpansion
    echo --- enabled delayed expansion chokes down unescaped exclamation marks^^^! "^!"
    for /F "usebackq delims=" %%G in ("%_auxFile%") do (
      set "_auxLine=%%~G"
      echo loop var=%%~G
      echo _auxLine=!_auxLine!
    )
  ENDLOCAL
  echo(
  SETLOCAL DisableDelayedExpansion
    echo --- toggled delayed expansion works although might be laborious!
    for /F "usebackq delims=" %%G in ("%_auxFile%") do (
      set "_auxLine=%%G"
      echo loop var=%%G
      SETLOCAL EnableDelayedExpansion
        echo _auxLine=!_auxLine!
      ENDLOCAL
    )
  ENDLOCAL
  echo(
  SETLOCAL DisableDelayedExpansion
    echo --- keep delayed expansion DISABLED: use CALL command!
    for /F "usebackq delims=" %%G in ("%_auxFile%") do (
      set "_auxLine=%%G"
      echo loop var=%%G
      call :ProcessVar
    )
  ENDLOCAL

  rem delete the sample file
  del "%_auxFile%"
ENDLOCAL
goto :eof

:ProcessVar
  echo _auxLine=%_auxLine%
  echo WARNING: neither !_auxLine! nor %%G loop variable is available here!  
goto :eof

Notez que le script ci-dessus montre les bonnes façons de s'échapper

  • % signe pour cent par %% le doubler (l'expansion retardée n'a pas d'importance), et
  • ! point d'exclamation si l'expansion différée est activée:
    • "^!" s'il est placé entre deux guillemets doubles, utilisez le cmd et le caractère d'échappement général du script batch ^ caret;
    • ^^^! sinon, utilisez trois ^ carets.

Sortie :

==> D:\bat\SO\10558316.bat

--- file content
this line is 100% valid! Sure! Hurrah!

--- enabled delayed expansion chokes down unescaped exclamation marks! "!"
loop var=this line is 100% valid Hurrah
_auxLine=this line is 100% valid Hurrah

--- toggled delayed expansion works although might be laborious!
loop var=this line is 100% valid! Sure! Hurrah!
_auxLine=this line is 100% valid! Sure! Hurrah!

--- keep delayed expansion DISABLED: use CALL command!
loop var=this line is 100% valid! Sure! Hurrah!
_auxLine=this line is 100% valid! Sure! Hurrah!
WARNING: !_auxLine! as well as %G loop variables are not available here!

==>
8
JosefZ