2011-07-13 66 views
36

noto en la mayoría de los guiones, los dos son por lo general en la misma línea que así:¿Cómo funcionan SETLOCAL y ENABLEDELAYEDEXPANSION?

SETLOCAL ENABLEDELAYEDEXPANSION 

son los dos comandos separados de hecho y se puede escribir en líneas separadas?

¿La configuración ENABLEDELAYEDEXPANSION tendrá un efecto adverso en un script si está configurado en las primeras líneas del script y no se desactiva hasta el final del script?

+0

suelo poner esa línea en la parte superior de casi todos mis scripts y rara vez causa un problema, y ​​me gusta cómo maneja mejor los caracteres de escape, especialmente al analizar XML o HTML. – djangofan

+0

@djangofan ¿ha analizado el uso de AutoIt para tales tareas? Lo recomiendo Me alejé de batch/powershell/vbscript para AutoIt. – Mechaflash

+2

Sí, he oído hablar de él. tal vez lo mire más de cerca. Aunque no me gusta pedir cosas de terceros ... y parece que también podría usar Powershell si ese es el caso. – djangofan

Respuesta

15

ENABLEDELAYEDEXPANSION es un parámetro que recibe el comando SETLOCAL (mira setlocal /?)

Su efecto vive por la duración de la secuencia de comandos, o un ENDLOCAL:

Al final de un archivo por lotes es alcanzado, un implícito ENDLOCAL es ejecutado para cualquier comando pendiente SETLOCAL emitido por ese script de lote .

En particular, esto significa que si utiliza SETLOCAL ENABLEDELAYEDEXPANSION en un script, a menos que any environment variable changes are lost at the end of ittake special measures.

+6

¿qué tal la segunda parte de la pregunta? – Mechaflash

+0

Bueno, solo tendría un efecto adverso si lo habilitó, luego escribió algún código que se comportó de manera diferente si no fuera en –

+0

No es probable, pero es cierto. – djangofan

8

La parte ENABLEDELAYEDEXPANSION ES OBLIGATORIA en ciertos programas que usan expansión diferida, es decir, que toma el valor de las variables que se modificaron dentro de los comandos IF o FOR al incluir sus nombres en signos de admiración.

Si habilita esta expansión en una secuencia de comandos que no lo requiere, la secuencia de comandos se comporta diferente solo si contiene nombres incluidos en exclamación-marks! LIKE! !¡ESTAS!. Por lo general, el nombre solo se borra, pero si existe una variable con el mismo nombre por casualidad, el resultado es impredecible y depende del valor de dicha variable y del lugar donde aparece.

La parte SETLOCAL SE REQUIERE en solo unos pocos programas especializados (recursivos), pero se usa comúnmente cuando quiere asegurarse de no modificar ninguna variable existente con el mismo nombre por casualidad o si desea eliminar automáticamente todo el variables utilizadas en su programa. Sin embargo, debido a que no hay un comando separado para habilitar la expansión retrasada, los programas que lo requieren también deben incluir la parte SETLOCAL.

+0

Con EnableDelayedExpansion tienes incluso problemas si tu texto contiene solo un '!' Como 'echo Hello!' Y con un signo de exclamación en una línea también obtienes problemas con los carets 'echo" Caret^"se ha ido!' – jeb

81

Creo que debe entender qué retraso de expansión es. Las respuestas existentes no lo explican (suficientemente) en mi humilde opinión.

Typing SET /? explica lo razonablemente bien:

entorno retardada expansión de variables es útil para moverse por las limitaciones de la actual expansión que se produce cuando se lee una línea de texto, no cuando se ejecuta . El siguiente ejemplo demuestra el problema inmediato la expansión de variables:

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

nunca mostrar el mensaje, ya que el% VAR% en ambos IF es sustituido cuando la primera instrucción IF se lee, ya que lógicamente incluye el cuerpo del IF, que es una declaración compuesta.Entonces, el IF dentro de la declaración compuesta realmente compara "antes" con "después", que nunca será igual. Del mismo modo, el ejemplo siguiente no funcionará como se esperaba:

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

en que no va a construir una lista de archivos en el directorio actual, sino que simplemente va a establecer la variable de lista hasta el último archivo encontrado. De nuevo, esto se debe a que% LIST% se expande solo una vez cuando se lee la instrucción FOR , y en ese momento la variable LIST está vacía. Por lo que el bucle FOR real que estamos ejecutando es:

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

la que sólo mantiene la configuración lista hasta el último archivo encontrado.

La expansión de variable de entorno retrasada le permite utilizar un carácter diferente de (el signo de exclamación) para expandir las variables de entorno al tiempo de ejecución. Si se habilita la expansión de variables de retraso, los ejemplos anteriores podrían escribirse de la siguiente manera a funcionar como está previsto:

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% 

Otro ejemplo es este archivo por lotes:

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

Esto imprime x2 y y2: cada 1 es reemplazado por un 2.

Sin setlocal enabledelayedexpansion, los signos de exclamación son solo eso, por lo que se hará eco de !b:1=2! dos veces.

Debido a que las variables de entorno normales se expanden cuando un (bloque) declaración es leer, ampliando %b:1=2% utiliza el valor b tiene antes del bucle: z2 (pero y2 cuando no está establecido).

+0

Para ser claros, la expansión demorada no hace nada si no hay signos de exclamación en sus comandos, ¿no? –

+1

¡Correcto! Los signos de exclamación tienen otros, sutiles [efectos] (https://ss64.com/nt/delayedexpansion.html). –

0

A menudo existe un problema real porque las variables establecidas en el interior no se exportarán cuando termine ese archivo por lotes. Entonces no es posible exportar, lo que nos causó problemas. Como resultado, acabo de configurar el registro SIEMPRE utilizado la expansión retrasada (no sé por qué no es el predeterminado, podría ser un problema de compatibilidad de velocidad o herencia).

+3

A lo largo de los años de uso de archivos por lotes, he agregado automáticamente esa directiva a todos y cada uno de ellos y nunca la apago. No llegaría tan lejos como para habilitarlo de manera predeterminada para un sistema porque nunca se sabe si un script por lotes ejecutado por el sistema o los scripts por lotes de otras compañías pueden tener conflictos con él. Este ES el Windows del que estamos hablando;) – Mechaflash

Cuestiones relacionadas