(Lote de Windows) Ir a dentro si el bloque se comporta de manera muy extraña

Si tomo el siguiente fragmento de código de lote de Windows y lo ejecuto:

echo foo if 1 == 1 ( echo bar goto asdf :asdf echo baz ) else ( echo quux ) 

La salida que esperaría es:

 foo bar baz 

Pero en cambio me da:

 foo bar baz quux 

Si hago un comentario sobre la línea goto asdf , arroja la salida que espero. La línea de echo quux nunca debe ejecutarse, entonces, ¿por qué la existencia del goto hace que eso suceda?

ACTUALIZACIÓN: por lo que vale, aquí hay una solución que hace correctamente lo que originalmente pretendía:

 goto BEGIN :doit echo bar goto asdf :asdf echo baz goto :EOF :BEGIN echo foo if 1 == 1 ( call :doit ) else ( echo quux ) 

Sin embargo, esto no responde mi pregunta original.

El objective de un CALL o GOTO nunca debe estar dentro de una instrucción de bloque entre paréntesis. Se puede hacer, pero como puede ver, los resultados probablemente no serán los que usted desea.

Toda la construcción IF (…) ELSE (…) se analiza y se carga en la memoria antes de que se procese. En otras palabras, se trata lógicamente como una línea de código. Después de analizarlo, CMD.EXE espera reanudar el análisis comenzando con la siguiente línea después de la construcción IF / ELSE.

Después de la fase de análisis, el comando complejo se ejecuta desde la memoria. La cláusula IF se procesa correctamente y la cláusula ELSE se omite correctamente. PERO dentro de la cláusula IF (verdadera), realiza un GOTO :asdf , por lo que CMD.EXE comienza a escanear la etiqueta. Comienza al final de IF / ELSE y escanea hasta el final del archivo, regresa a la parte superior y escanea hasta que encuentra la etiqueta. La etiqueta pasa a estar dentro de su cláusula IF, pero el escáner de tags no sabe nada sobre ese detalle. Entonces, cuando el comando complejo termina de ejecutarse desde la memoria, el proceso por lotes se reanuda desde la etiqueta en lugar de desde el final del complejo IF / ELSE.

Entonces, en este punto, el procesador de lotes ve y ejecuta las siguientes líneas

  echo baz ) else ( echo quux ) 

baz tiene eco, y también quux. Pero podría preguntar: “¿Por qué no? ) else ( y / o ) generar un error de syntax, ya que ahora están desequilibrados y ya no se analizan como parte de la statement IF más grande.

Eso es por cómo ) se maneja.

Si hay un abierto ( activo cuando ) se encuentra, entonces el ) se procesa como es de esperar.

Pero si el analizador está esperando un comando y encuentra a ) cuando no hay un abrir activo ( , entonces el ) se ignora y todos los caracteres en el rest de la línea se ignoran. Efectivamente el ) ahora está funcionando como una statement REM.

Cualquier cosa dentro de un conjunto de corchetes se considera como una sola línea, procesada, interpretada y ejecutada en un golpe. Su script alcanza goto asdf y salta de ese bloque / línea. En la etiqueta :asdf , no hay corchete, por lo que comienza a leer líneas una a una. Llega a else , pero no hay if entre :asdf y else por lo que lo ignora.

Para evitar problemas como este, siempre uso goto o goto if y for lugar de bloques. Esto resuelve problemas con declaraciones goto adicionales y también soluciona muchos problemas con variables.

Para usar goto :

 echo foo if 1 == 1 goto bar echo quux goto nextbit :bar echo bar goto asdf :asdf echo baz :nextbit :: more script... 

O para usar la call :

 echo foo if 1 == 1 (call :bar) else (call :quux) :: more script... exit /b :bar echo bar goto asdf :asdf echo baz exit /b :quux echo quux exit /b 

En este caso, se relaciona con el pobre anidamiento y la estructura de un bucle dentro de una statement IF, como se explica claramente en https://stackoverflow.com/users/1012053/dbenham anteriormente.

Dicho esto, descubrí otra consideración similar debido a este problema … Por favor, eche un vistazo al siguiente problema y la siguiente solución aquí: “. Fue inesperado en este momento” generado a partir de la línea de script por lotes ‘if exist [file] (. ..

La solución fue simplemente el tratamiento de ‘(‘ y ‘)’ en líneas ECHO dentro de un bloque de instrucciones IF.

El punto es, considere el tratamiento de caracteres especiales como una posible fuente de problemas al resolver problemas de declaraciones IF (y posiblemente FOR).

HTH