Example of delayed expansion in batch file

前端 未结 3 448
长发绾君心
长发绾君心 2020-11-21 14:40

Can someone give me an example of where a batch script would act differently with or without delayed expansion? Are there any situations where you would NOT want to use del

相关标签:
3条回答
  • 2020-11-21 15:18

    I wanted to add a great example on how "EnableDelayedExpansion" (EDE) can be useful outside of the ubiquitous FOR loop examples.

    Here is a line of earthquake data that I wish to parse (I call it it 1line.txt)

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

    The problem I ran into was that last segment of this line does not always start at the same column number. So I needed to create a flexible SET command that will accurately pluck out the last segment of this line.

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

    EDE allows me to place a variable (where) inside another variable (line). EDE will translate the variable bracketed by % first, then process the variable bracketed by ! and (in this case) push out the results into the "locate" variable.

    0 讨论(0)
  • 2020-11-21 15:24

    Max's answer gives an example of where a batch script would act differently with or without delayed expansion.

    For the sake of completeness, let's answer another part of the question and show a situation where you would NOT want to use delayed expansion when your data contain an exclamation mark ! (and show two ways of processing such data):

    @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
    

    Note that above script shows proper ways of escaping

    • % percent sign by %% doubling it (delayed expansion does not matter), and
    • ! exclamation mark if delayed expansion is enabled:
      • "^!" if enclosed in a pair of double quotes, then use the cmd and batch-script general escape character ^ caret;
      • ^^^! otherwise, use three ^ carets.

    Output:

    ==> 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!
    
    ==>
    
    0 讨论(0)
  • 2020-11-21 15:32

    Look at the following examples...

    Example 1: The following code DOESN'T use delayed expansion, so the variables in the for loop are expanded only one time. This means that %Count% will always expand to 0 in each iteration of the loop, no matter what we do to it with the set command:

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

    So this script will output:

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

    This is not how this loop is supposed to work.

    Example 2: On the other hand, if we use delayed expansion, we have the following script, which will run as expected.

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

    and, as expected, it will output:

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

    When you use the ENABLEDELAYEDEXPANSION, and expand a variable using ! instead of %, the variable is re-expanded each time, and everything works as it's supposed to.

    0 讨论(0)
提交回复
热议问题