Ejemplo de expansión retrasada en un archivo por lotes
¿Alguien puede darme un ejemplo de dónde un script por lotes actuaría de manera diferente con o sin expansión retrasada? ¿Existe alguna situación en la que NO desee utilizar la expansión retrasada? Gracias.
Mira los siguientes ejemplos...
Ejemplo 1: el siguiente código NO utiliza expansión retrasada, por lo que las variables en el bucle for se expanden solo una vez. Esto significa que %Count%
siempre se expandirá 0
en cada iteración del bucle, sin importar lo que le hagamos con el comando set:
@echo off
set COUNT=0
for %%v in (1 2 3 4) do (
set /A COUNT=%COUNT% + 1
echo Count = %COUNT%
)
pause
Entonces este script generará:
Count = 0
Count = 0
Count = 0
Count = 0
No es así como se supone que funciona este bucle.
Ejemplo 2: Por otro lado, si usamos expansión retrasada, tenemos el siguiente script, que se ejecutará como se esperaba.
setlocal ENABLEDELAYEDEXPANSION
set COUNT=0
for %%v in (1 2 3 4) do (
set /A COUNT=!COUNT! + 1
echo Count = !COUNT!
)
pause
y, como se esperaba, generará:
Count = 1
Count = 2
Count = 3
Count = 4
Cuando usa ENABLEDELAYEDEXPANSION
y expande una variable usando !
en lugar de %
, la variable se vuelve a expandir cada vez y todo funciona como se supone que debe hacerlo.
Quería agregar un gran ejemplo sobre cómo "EnableDelayedExpansion" (EDE) puede ser útil fuera de los omnipresentes ejemplos de bucle FOR.
Aquí hay una línea de datos de terremotos que deseo analizar (la llamo 1line.txt)
ak_11574812 2015.04.29.193822 62.9525 -148.8849 1.0 9.5 1 49 km al sur de Cantwell, Alaska
El problema con el que me encontré fue que el último segmento de esta línea no siempre comienza en el mismo número de columna. Entonces necesitaba crear un comando SET flexible que arrancara con precisión el último segmento de esta línea.
ECHO OFF
setlocal enableDelayedExpansion
set where=72
set /p line=<1line.txt
set locate=!line:~%where%,28!
echo %locate%
EDE me permite colocar una variable (dónde) dentro de otra variable (línea). EDE traducirá primero la variable entre corchetes % y luego procesará la variable entre corchetes ! y (en este caso) enviar los resultados a la variable "localizar".
La respuesta de Max da un ejemplo de dónde un script por lotes actuaría de manera diferente con o sin expansión retrasada .
Para completar, respondamos otra parte de la pregunta y mostremos una situación en la que NO desearía utilizar la expansión retrasada cuando sus datos contienen un signo de exclamación !
(y mostraremos dos formas de procesar dichos datos):
@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
Tenga en cuenta que el script anterior muestra formas adecuadas de escapar
%
signo de porcentaje%%
duplicándolo (la expansión retrasada no importa), y!
signo de exclamación si la expansión retrasada está habilitada:"^!"
si está entre comillas dobles, utilice elcmd
carácter de intercalación de escape general del script por lotes y^
;^^^!
de lo contrario, utilice tres^
signos de intercalación.
Producción :
==> 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!
==>