Realizamos experimentos para investigar la gramática de los scripts por lotes. También investigamos las diferencias entre el modo de línea de comandos y el lote.
Analizador de línea de lote:
Aquí hay una breve descripción de las fases en el analizador de línea de archivo por lotes:
Fase 0) Leer línea:
Fase 1) Porcentaje de expansión:
Fase 2) Procesar caracteres especiales, tokenizar y construir un bloque de comandos en caché: este es un proceso complejo que se ve afectado por cosas como comillas, caracteres especiales, delimitadores de tokens y escapes de caret.
Fase 3) Haga eco de los comandos analizados solo si el bloque de comandos no comenzó @
y ECHO estaba ENCENDIDO al comienzo del paso anterior.
Fase 4) %X
Expansión variable FOR : solo si un comando FOR está activo y los comandos después de DO están siendo procesados.
Fase 5) Expansión retrasada: solo si la expansión retrasada está habilitada
Fase 5.3) Procesamiento de tubería: solo si los comandos están a ambos lados de una tubería
Fase 5.5) Ejecutar redireccionamiento:
Fase 6) Procesamiento de LLAMADAS / Duplicación de Caret: solo si el token de comando es LLAMADA
Fase 7) Ejecutar: el comando se ejecuta
Aquí hay detalles para cada fase:
Tenga en cuenta que las fases que se describen a continuación son solo un modelo de cómo funciona el analizador por lotes. Las partes internas reales de cmd.exe pueden no reflejar estas fases. Pero este modelo es efectivo para predecir el comportamiento de los scripts por lotes.
Fase 0) Leer línea: lea la línea de entrada hasta el primero <LF>
.
- Al leer una línea para analizarla como un comando,
<Ctrl-Z>
(0x1A) se lee como <LF>
(LineFeed 0x0A)
- Cuando GOTO o llamada se leen las líneas durante la exploración para un: etiqueta,
<Ctrl-Z>
, se trata como en sí - se no se convirtió al<LF>
Fase 1) Porcentaje de expansión:
- Un doble
%%
es reemplazado por un sencillo%
- La expansión de argumentos (
%*
, %1
, %2
, etc.)
- Expansión de
%var%
, si var no existe, reemplácelo con nada
- La línea se trunca al principio
<LF>
no dentro de la %var%
expansión
- Para una explicación completa, lea la primera mitad de esto de dbenham Mismo hilo: Fase porcentual
Fase 2) Procesar caracteres especiales, tokenizar y construir un bloque de comandos en caché: este es un proceso complejo que se ve afectado por cosas como comillas, caracteres especiales, delimitadores de tokens y escapes de caret. Lo que sigue es una aproximación de este proceso.
Hay conceptos que son importantes a lo largo de esta fase.
- Una ficha es simplemente una cadena de caracteres que se trata como una unidad.
- Las fichas están separadas por delimitadores de fichas. Los delimitadores de token estándar son
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
y los <0xFF>
delimitadores de token consecutivos se tratan como uno: no hay tokens vacíos entre los delimitadores de token
- No hay delimitadores de token dentro de una cadena entre comillas. La cadena completa entre comillas siempre se trata como parte de un token único. Un solo token puede consistir en una combinación de cadenas entre comillas y caracteres sin comillas.
Los siguientes caracteres pueden tener un significado especial en esta fase, según el contexto: <CR>
^
(
@
&
|
<
>
<LF>
<space>
<tab>
;
,
=
<0x0B>
<0x0C>
<0xFF>
Mira cada personaje de izquierda a derecha:
- Si
<CR>
luego, elimínelo, como si nunca hubiera estado allí (excepto por un extraño comportamiento de redireccionamiento )
- Si un símbolo de intercalación (
^
), se escapa el siguiente carácter y se elimina el símbolo de interferencia de escape. Los personajes escapados pierden todo significado especial (excepto <LF>
).
- Si se trata de una cita (
"
), alterna el indicador de cita. Si la bandera de cotización está activo, entonces solamente "
y <LF>
son especiales. Todos los demás personajes pierden su significado especial hasta que la próxima cita desactiva la bandera de la cita. No es posible escapar de la cita de cierre. Todos los caracteres entre comillas siempre están dentro del mismo token.
<LF>
siempre apaga la bandera de cotización. Otros comportamientos varían según el contexto, pero las citas nunca alteran el comportamiento de <LF>
.
- Escapado
<LF>
<LF>
es despojado
- El siguiente personaje se escapa. Si al final del búfer de línea, la siguiente línea se lee y procesa en las fases 1 y 1.5 y se agrega a la actual antes de escapar del siguiente carácter. Si el siguiente carácter es
<LF>
, entonces se trata como un literal, lo que significa que este proceso no es recursivo.
- Sin escapes
<LF>
no entre paréntesis
<LF>
se elimina y se termina el análisis de la línea actual.
- Los caracteres restantes en el búfer de línea simplemente se ignoran.
- Sin escapes
<LF>
dentro de un bloque entre paréntesis FOR IN
<LF>
se convierte en un <space>
- Si al final del búfer de línea, la siguiente línea se lee y se agrega a la actual.
- Sin escapes
<LF>
dentro de un bloque de comandos entre paréntesis
<LF>
se convierte <LF><space>
y <space>
se trata como parte de la siguiente línea del bloque de comandos.
- Si al final del búfer de línea, la siguiente línea se lee y se agrega al espacio.
- Si es uno de los caracteres especiales
&
|
<
o >
, divida la línea en este punto para manejar tuberías, concatenación de comandos y redirección.
- En el caso de una tubería (
|
), cada lado es un comando separado (o bloque de comandos) que recibe un manejo especial en la fase 5.3
- En el caso de
&
, &&
o ||
concatenación de comando, cada lado de la concatenación se trata como un comando separado.
- En el caso de
<
, <<
, >
, o >>
redirección, la cláusula de redirección se analiza, elimina temporalmente, y luego añade al final de la consigna de corriente. Una cláusula de redirección consta de un dígito de identificador de archivo opcional, el operador de redirección y el token de destino de redirección.
- Si el token que precede al operador de redirección es un único dígito sin escape, entonces el dígito especifica el identificador de archivo que se debe redirigir. Si no se encuentra el token del identificador, la redirección de salida predeterminada es 1 (stdout) y la redirección de entrada predeterminada es 0 (stdin).
- Si el primer token para este comando (antes de mover la redirección al final) comienza
@
, entonces @
tiene un significado especial. ( @
no es especial en ningún otro contexto)
- El especial
@
se elimina.
- Si ECHO está activado, este comando, junto con los siguientes comandos concatenados en esta línea, se excluyen del eco de la fase 3. Si
@
está antes de una apertura (
, se excluye todo el bloque entre paréntesis del eco de fase 3.
- Paréntesis de proceso (proporciona enunciados compuestos en varias líneas):
- Si el analizador no está buscando un token de comando, entonces
(
no es especial.
- Si el analizador busca un token de comando y lo encuentra
(
, inicie una nueva declaración compuesta e incremente el contador de paréntesis
- Si el contador de paréntesis es> 0,
)
termina la declaración compuesta y disminuye el contador de paréntesis.
- Si se alcanza el final de la línea y el contador de paréntesis es> 0, la siguiente línea se agregará a la declaración compuesta (comienza de nuevo con la fase 0)
- Si el contador de paréntesis es 0 y el analizador está buscando un comando, entonces
)
funciona de manera similar a una REM
declaración siempre que sea seguido inmediatamente por un delimitador de token, un carácter especial, una nueva línea o el final del archivo
- Todos los caracteres especiales pierden su significado excepto
^
(es posible la concatenación de líneas)
- Una vez que se alcanza el final de la línea lógica, se descarta todo el "comando".
- Cada comando se analiza en una serie de tokens. El primer token siempre se trata como un token de comando (después de que los especiales
@
se hayan eliminado y la redirección se haya movido al final).
- Los delimitadores de token iniciales antes del token de comando se eliminan
- Al analizar el token de comando,
(
funciona como un delimitador de token de comando, además de los delimitadores de token estándar
- El manejo de los tokens posteriores depende del comando.
- La mayoría de los comandos simplemente concatenan todos los argumentos después del token de comando en un solo token de argumento. Todos los delimitadores de token de argumento se conservan. Las opciones de argumento generalmente no se analizan hasta la fase 7.
- Tres comandos obtienen un manejo especial: IF, FOR y REM
- IF se divide en dos o tres partes distintas que se procesan de forma independiente. Un error de sintaxis en la construcción IF dará como resultado un error de sintaxis fatal.
- La operación de comparación es el comando real que fluye hasta la fase 7
- Todas las opciones de IF se analizan completamente en la fase 2.
- Los delimitadores de tokens consecutivos colapsan en un solo espacio.
- Dependiendo del operador de comparación, habrá uno o dos tokens de valor que se identificarán.
- El bloque de comandos True es el conjunto de comandos después de la condición y se analiza como cualquier otro bloque de comandos. Si se va a utilizar ELSE, entonces el bloque True debe estar entre paréntesis.
- El bloque de comando False opcional es el conjunto de comandos después de ELSE. De nuevo, este bloque de comando se analiza normalmente.
- Los bloques de comandos Verdadero y Falso no fluyen automáticamente a las fases posteriores. Su procesamiento posterior es controlado por la fase 7.
- FOR se divide en dos después de la DO. Un error de sintaxis en la construcción FOR dará como resultado un error de sintaxis fatal.
- La porción a través de DO es el comando de iteración FOR real que fluye a través de la fase 7
- Todas las opciones FOR se analizan completamente en la fase 2.
- La cláusula IN entre paréntesis trata
<LF>
como <space>
. Después de analizar la cláusula IN, todos los tokens se concatenan juntos para formar un solo token.
- Los delimitadores de tokens consecutivos sin escape / sin comillas colapsan en un solo espacio a lo largo del comando FOR a través de DO.
- La porción después de DO es un bloque de comando que se analiza normalmente. El procesamiento posterior del bloque de comando DO se controla mediante la iteración en la fase 7.
- REM detectado en la fase 2 se trata dramáticamente diferente que todos los otros comandos.
- Solo se analiza un token de argumento: el analizador ignora los caracteres después del primer token de argumento.
- El comando REM puede aparecer en la salida de la fase 3, pero el comando nunca se ejecuta y se repite el texto del argumento original: no se eliminan los escapes, excepto ...
- Si solo hay un token de argumento que termina con un no escapado
^
que termina la línea, entonces el token de argumento se descarta y la línea posterior se analiza y se agrega al REM. Esto se repite hasta que haya más de una ficha o el último carácter no ^
.
- Si el token de comando comienza con
:
, y esta es la primera ronda de la fase 2 (no un reinicio debido a CALL en la fase 6), entonces
- El token normalmente se trata como una etiqueta no ejecutada .
- El resto de la línea se analiza, sin embargo
)
, <
, >
, &
y |
ya no tienen un significado especial. Todo el resto de la línea se considera parte de la etiqueta "comando".
- El
^
sigue siendo especial, lo que significa que de continuación de línea se puede utilizar para añadir una línea posterior a la etiqueta.
- Una etiqueta no ejecutada dentro de un bloque entre paréntesis dará como resultado un error de sintaxis fatal a menos que sea seguido inmediatamente por un comando o una etiqueta ejecutada en la siguiente línea.
(
ya no tiene un significado especial para el primer comando que sigue a la etiqueta no ejecutada .
- El comando se cancela después de completar el análisis de etiquetas. Las fases posteriores no tienen lugar para la etiqueta
- Existen tres excepciones que pueden hacer que una etiqueta que se encuentra en la fase 2 se trate como una etiqueta ejecutada que continúa analizando a través de la fase 7.
- No hay cambio de dirección que precede a la etiqueta de la señal, y hay una
|
tubería o &
, &&
o ||
concatenación de comando en la línea.
- Hay una redirección que precede al token de la etiqueta, y el comando está dentro de un bloque entre paréntesis.
- El token de etiqueta es el primer comando en una línea dentro de un bloque entre paréntesis, y la línea de arriba terminó con una etiqueta no ejecutada .
- Lo siguiente ocurre cuando se descubre una etiqueta ejecutada en la fase 2
- La etiqueta, sus argumentos y su redirección están excluidos de cualquier salida de eco en la fase 3
- Cualquier comando concatenado posterior en la línea se analiza y ejecuta por completo.
- Para obtener más información sobre las etiquetas Ejecutado vs. etiquetas no ejecutados , ver https://www.dostips.com/forum/viewtopic.php?f=3&t=3803&p=55405#p55405
Fase 3) Haga eco de los comandos analizados solo si el bloque de comandos no comenzó @
y ECHO estaba ENCENDIDO al comienzo del paso anterior.
Fase 4) %X
Expansión variable FOR : solo si un comando FOR está activo y los comandos después de DO están siendo procesados.
- En este punto, la fase 1 de procesamiento por lotes ya se habrá convertido una para la variable como
%%X
en %X
. La línea de comando tiene diferentes reglas de expansión porcentual para la fase 1. Esta es la razón por la que las líneas de comando usan %X
pero los archivos %%X
por lotes usan las variables FOR.
- Los nombres de las variables FOR distinguen entre mayúsculas y minúsculas, pero
~modifiers
no distinguen entre mayúsculas y minúsculas.
~modifiers
tienen prioridad sobre los nombres de variables. Si el siguiente carácter ~
es un modificador y un nombre de variable FOR válido, y existe un carácter posterior que es un nombre de variable FOR activo, entonces el carácter se interpreta como un modificador.
- Los nombres de las variables FOR son globales, pero solo dentro del contexto de una cláusula DO. Si una rutina se llama desde una cláusula FOR DO, las variables FOR no se expanden dentro de la rutina CALLed. Pero si la rutina tiene su propio comando FOR, entonces todas las variables FOR definidas actualmente son accesibles para los comandos DO internos.
- Los nombres de variables FOR se pueden reutilizar dentro de FOR anidados. El valor FOR interno tiene prioridad, pero una vez que se cierra el FOR interno, se restaura el valor FOR externo.
- Si ECHO estaba ENCENDIDO al comienzo de esta fase, entonces se repite la fase 3) para mostrar los comandos de OD analizados después de que las variables FOR se hayan expandido.
---- A partir de este punto, cada comando identificado en la fase 2 se procesa por separado.
---- Las fases 5 a 7 se completan para un comando antes de pasar al siguiente.
Fase 5) Expansión retrasada: solo si la expansión retrasada está activada, el comando no está en un bloque entre paréntesis a cada lado de una tubería , y el comando no es un script por lotes "desnudo" (nombre del script sin paréntesis, CALL, concatenación de comandos, o tubería).
- Cada token para un comando se analiza para una expansión retrasada de forma independiente.
- La mayoría de los comandos analizan dos o más tokens: el token de comando, el token de argumentos y cada token de destino de redirección.
- El comando FOR analiza solo el token de la cláusula IN.
- El comando IF solo analiza los valores de comparación, ya sea uno o dos, dependiendo del operador de comparación.
- Para cada ficha analizada, primero verifique si contiene alguna
!
. Si no, entonces el token no se analiza, importante para los ^
personajes. Si el token contiene !
, entonces escanea cada personaje de izquierda a derecha:
- Si se trata de un símbolo de intercalación (
^
), el siguiente carácter no tiene un significado especial, el símbolo de intercalación en sí mismo se elimina
- Si se trata de un signo de exclamación, busque el siguiente signo de exclamación (ya no se observan los signos de interrogación), amplíe el valor de la variable.
- Las aperturas consecutivas
!
se colapsan en una sola!
- Cualquier resto no emparejado
!
se elimina
- La expansión de vars en esta etapa es "segura", ya que los caracteres especiales ya no se detectan (incluso
<CR>
o <LF>
)
- Para una explicación más completa, lea la segunda mitad de esto del mismo hilo de dbenham
- Fase del punto de exclamación
Fase 5.3) Procesamiento de tubería: solo si los comandos están a cada lado de una tubería
Cada lado de la tubería se procesa de forma independiente y asíncrona.
- Si el comando es interno a cmd.exe, o es un archivo por lotes, o si es un bloque de comando entre paréntesis, entonces se ejecuta en un nuevo hilo cmd.exe a través de
%comspec% /S /D /c" commandBlock"
, por lo que el bloque de comando obtiene un reinicio de fase, pero esta vez en modo de línea de comando.
- Si se
<LF>
trata de un bloque de comandos entre paréntesis, todos los que tienen un comando antes y después se convierten a <space>&
. Otros <LF>
son despojados.
- Este es el final del procesamiento de los comandos de tubería.
- Consulte ¿Por qué falla la expansión retrasada cuando se encuentra dentro de un bloque de código canalizado? para más información sobre el análisis y procesamiento de tuberías
Fase 5.5) Ejecutar redireccionamiento: cualquier redirección que se descubrió en la fase 2 ahora se ejecuta.
Fase 6) Procesamiento de LLAMADA / duplicación de Caret: solo si el token de comando es CALL, o si el texto antes del primer delimitador de token estándar es CALL. Si CALL se analiza desde un token de comando más grande, la parte no utilizada se antepone al token de argumentos antes de continuar.
- Escanee el token de argumentos para encontrar uno sin comillas
/?
. Si se encuentra en algún lugar dentro de los tokens, entonces cancele la fase 6 y continúe con la Fase 7, donde se imprimirá la AYUDA para la LLAMADA.
- Elimine el primero
CALL
, para que se puedan apilar varias LLAMADAS
- Doblar todos los cuidados
- Reinicie las fases 1, 1.5 y 2, pero no continúe con la fase 3
- Cualquier cuidado duplicado se reduce de nuevo a un cuidado, siempre que no se cite. Pero desafortunadamente, las citas citadas siguen duplicadas.
- La fase 1 cambia un poco
- Los errores de expansión en el paso 1.2 o 1.3 anulan la LLAMADA, pero el error no es fatal: el procesamiento por lotes continúa.
- Las tareas de la fase 2 se alteran un poco
- Se detecta cualquier nueva redirección sin comillas y sin escape que no se detectó en la primera ronda de la fase 2, pero se elimina (incluido el nombre del archivo) sin realizar realmente la redirección
- Se elimina cualquier caret sin comillas y sin escape que aparece recientemente al final de la línea sin realizar la continuación de la línea
- La LLAMADA se cancela sin error si se detecta alguno de los siguientes
- Recién aparecido sin comillas, sin escapes
&
o|
- El token de comando resultante comienza con sin comillas, sin escape
(
- La primera ficha después de que la LLAMADA eliminada comenzó con
@
- Si el comando resultante es un IF o FOR aparentemente válido, entonces la ejecución fallará posteriormente con un error que indica que
IF
o FOR
no se reconoce como un comando interno o externo.
- Por supuesto, la LLAMADA no se cancela en esta segunda ronda de la fase 2 si el token de comando resultante es una etiqueta que comienza con
:
.
- Si el token de comando resultante es CALL, reinicie la Fase 6 (se repite hasta que no haya más CALL)
- Si el token de comando resultante es un script por lotes o una etiqueta:, el resto de la Fase 6 maneja completamente la ejecución de la LLAMADA.
- Empuje la posición actual del archivo de script por lotes en la pila de llamadas para que la ejecución pueda reanudarse desde la posición correcta cuando se complete la LLAMADA.
- Configure los tokens de argumento% 0,% 1,% 2, ...% N y% * para CALL, utilizando todos los tokens resultantes
- Si el token de comando es una etiqueta que comienza con
:
, entonces
- Reinicie la Fase 5. Esto puede afectar lo que: la etiqueta está LLAMADA. Pero dado que los tokens% 0 etc. ya se han configurado, no alterará los argumentos que se pasan a la rutina CALLed.
- Ejecute la etiqueta GOTO para colocar el puntero del archivo al comienzo de la subrutina (ignore cualquier otra ficha que pueda seguir a la etiqueta:) Consulte la Fase 7 para conocer las reglas sobre cómo funciona GOTO.
- De lo contrario, transfiera el control al script por lotes especificado.
- La ejecución de CALLed: etiqueta o secuencia de comandos continúa hasta que se alcanza EXIT / B o fin de archivo, momento en el que se abre la pila CALL y la ejecución se reanuda desde la posición guardada del archivo.
La fase 7 no se ejecuta para scripts CALLed o: etiquetas.
- De lo contrario, el resultado de la fase 6 cae en la fase 7 para su ejecución.
Fase 7) Ejecutar: el comando se ejecuta
- 7.1 - Ejecutar comando interno : si se cita el token de comando, omita este paso. De lo contrario, intente analizar un comando interno y ejecutar.
- Las siguientes pruebas se realizan para determinar si un token de comando sin comillas representa un comando interno:
- Si el token de comando coincide exactamente con un comando interno, ejecútelo.
- De lo contrario, rompa el token de comando antes de la primera aparición de
+
/
[
]
<space>
<tab>
,
;
o =
Si el texto anterior es un comando interno, recuerde ese comando
- Si está en modo de línea de comando, o si el comando proviene de un bloque entre paréntesis, SI es un bloque de comando verdadero o falso, un bloque de comando FOR DO o está involucrado con la concatenación de comandos, ejecute el comando interno
- De lo contrario (debe ser un comando independiente en modo por lotes) escanee la carpeta actual y la RUTA en busca de un archivo .COM, .EXE, .BAT o .CMD cuyo nombre base coincida con el token de comando original
- Si el primer archivo coincidente es .BAT o .CMD, vaya a 7.3.exec y ejecute ese script
- De lo contrario (coincidencia no encontrada o primera coincidencia es .EXE o .COM) ejecute el comando interno recordado
- De lo contrario, rompa el token de comando antes de la primera aparición de
.
\
o :
Si el texto anterior no es un comando interno, vaya a 7.2. De lo
contrario, el texto anterior puede ser un comando interno. Recuerda este comando.
- Rompa el token de comando antes de la primera aparición de
+
/
[
]
<space>
<tab>
,
;
o =
Si el texto anterior es una ruta a un archivo existente, vaya a 7.2 De lo
contrario, ejecute el comando interno recordado.
- Si un comando interno se analiza desde un token de comando más grande, la parte no utilizada del token de comando se incluye en la lista de argumentos
- El hecho de que un token de comando se analice como un comando interno no significa que se ejecutará con éxito. Cada comando interno tiene sus propias reglas sobre cómo se analizan los argumentos y las opciones, y qué sintaxis está permitida.
- Todos los comandos internos imprimirán ayuda en lugar de realizar su función si
/?
se detecta. La mayoría reconoce /?
si aparece en alguna parte de los argumentos. Pero algunos comandos como ECHO y SET solo imprimen ayuda si el primer token de argumento comienza con /?
.
- SET tiene una semántica interesante:
- Si un comando SET tiene una comilla antes de habilitar el nombre de la variable y las extensiones
set "name=content" ignored
-> valor = content
entonces el texto entre el primer signo igual y la última comilla se usa como contenido (se excluyen la primera comilla y la última comilla). El texto después de la última cita se ignora. Si no hay comillas después del signo igual, entonces el resto de la línea se usa como contenido.
- Si un comando SET no tiene una comilla antes del nombre
set name="content" not ignored
-> valor = "content" not ignored
entonces el resto completo de la línea después del igual se usa como contenido, incluidas todas y cada una de las comillas que puedan estar presentes.
- Se evalúa una comparación IF, y dependiendo de si la condición es verdadera o falsa, se procesa el bloque de comando dependiente ya analizado, comenzando con la fase 5.
- La cláusula IN de un comando FOR se repite adecuadamente.
- Si este es un FOR / F que itera la salida de un bloque de comandos, entonces:
- La cláusula IN se ejecuta en un nuevo proceso cmd.exe a través de CMD / C.
- El bloque de comando debe pasar por todo el proceso de análisis por segunda vez, pero esta vez en un contexto de línea de comando
- ECHO comenzará ON, y la expansión demorada generalmente comenzará deshabilitada (dependiendo de la configuración del registro)
- Todos los cambios de entorno realizados por el bloque de comando de la cláusula IN se perderán una vez que finalice el proceso hijo cmd.exe
- Para cada iteración:
- Los valores de la variable FOR están definidos
- El bloque de comando DO ya analizado se procesa, comenzando con la fase 4.
- GOTO utiliza la siguiente lógica para ubicar la etiqueta:
- La etiqueta se analiza desde el primer token de argumento
- El script se escanea para la próxima aparición de la etiqueta
- El escaneo comienza desde la posición actual del archivo
- Si se alcanza el final del archivo, el escaneo vuelve al principio del archivo y continúa hasta el punto inicial original.
- El escaneo se detiene en la primera aparición de la etiqueta que encuentra, y el puntero del archivo se establece en la línea que sigue inmediatamente a la etiqueta. La ejecución del guión se reanuda desde ese punto. Tenga en cuenta que un verdadero GOTO exitoso anulará inmediatamente cualquier bloque de código analizado, incluidos los bucles FOR.
- Si no se encuentra la etiqueta o falta el token de la etiqueta, GOTO falla, se imprime un mensaje de error y se abre la pila de llamadas. Esto funciona efectivamente como EXIT / B, excepto que los comandos ya analizados en el bloque de comandos actual que siguen al GOTO todavía se ejecutan, pero en el contexto de CALLer (el contexto que existe después de EXIT / B)
- Consulte https://www.dostips.com/forum/viewtopic.php?f=3&t=3803 para obtener una descripción más precisa de las reglas utilizadas para analizar las etiquetas.
- RENAME y COPY aceptan comodines para las rutas de origen y destino. Pero Microsoft hace un trabajo terrible al documentar cómo funcionan los comodines, especialmente para la ruta de destino. Puede encontrar un conjunto útil de reglas comodín en ¿Cómo interpreta el comando RENAME de Windows los comodines?
- 7.2 - Ejecutar cambio de volumen - De lo contrario, si el token de comando no comienza con una cita, tiene exactamente dos caracteres y el segundo carácter es un signo de dos puntos, entonces cambie el volumen
- Todos los tokens de argumento son ignorados
- Si no se puede encontrar el volumen especificado por el primer carácter, entonces cancele con un error
- Una señal de comando de
::
siempre dará como resultado un error a menos que se use SUBST para definir un volumen para. ::
Si se usa SUBST para definir un volumen ::
, entonces el volumen se cambiará, no se tratará como una etiqueta.
- 7.3 - Ejecutar comando externo : en caso contrario, trate el comando como un comando externo.
- Si en el modo de línea de comandos y el comando no es citado y no comienza con una especificación de volumen, espacio en blanco,
,
, ;
, =
o +
luego romper el comando de token en la primera aparición de <space>
,
;
o =
y anteponer el resto al argumento token (s).
- Si el segundo carácter del token de comando es dos puntos, verifique que se pueda encontrar el volumen especificado por el primer carácter.
Si no puede encontrar el volumen, anule con un error.
- Si está en modo por lotes y el token de comando comienza con
:
, entonces vaya a 7.4
Tenga en cuenta que si el token de etiqueta comienza con ::
, entonces esto no se alcanzará porque el paso anterior habrá abortado con un error a menos que se use SUBST para definir un volumen ::
.
- Identifique el comando externo a ejecutar.
- Este es un proceso complejo que puede involucrar el volumen actual, el directorio actual, la variable PATH, la variable PATHEXT y / o las asociaciones de archivos.
- Si no se puede identificar un comando externo válido, anule con un error.
- Si en el modo de línea de comandos y el comando símbolo comienza con
:
y, a continuación Goto 7.4
Tenga en cuenta que esto rara vez se alcanza debido a que el paso anterior se habrá abortado con un error a menos que el símbolo de comandos comienza con ::
, y SUBST se utiliza para definir un volumen para ::
, y el el token de comando completo es una ruta válida a un comando externo.
- 7.3.exec : ejecuta el comando externo.
- 7.4 - Ignorar una etiqueta - Ignorar el comando y todos sus argumentos si el token de comando comienza con
:
.
Las reglas en 7.2 y 7.3 pueden evitar que una etiqueta llegue a este punto.
Analizador de línea de comando:
Funciona como el BatchLine-Parser, excepto:
Fase 1) Porcentaje de expansión:
- No
%*
, %1
expansión de argumentos etc.
- Si var no está definido, entonces no
%var%
se modifica.
- Sin manejo especial de
%%
. Si var = contenido, se %%var%%
expande a %content%
.
Fase 3) Eco los comandos analizados
- Esto no se realiza después de la fase 2. Solo se realiza después de la fase 4 para el bloque de comandos FOR DO.
Fase 5) Expansión retardada: solo si DelayedExpansion está habilitada
- Si var no está definido, entonces no
!var!
se modifica.
Fase 7) Ejecutar comando
- Los intentos de LLAMAR o GOTO a: la etiqueta dan como resultado un error.
- Como ya se documentó en la fase 7, una etiqueta ejecutada puede provocar un error en diferentes escenarios.
- Las etiquetas ejecutadas por lotes solo pueden causar un error si comienzan con
::
- Las etiquetas ejecutadas en la línea de comando casi siempre producen un error
Análisis de valores enteros
Hay muchos contextos diferentes donde cmd.exe analiza valores enteros de cadenas y las reglas son inconsistentes:
SET /A
IF
%var:~n,m%
(expansión de subcadena variable)
FOR /F "TOKENS=n"
FOR /F "SKIP=n"
FOR /L %%A in (n1 n2 n3)
EXIT [/B] n
Los detalles de estas reglas se pueden encontrar en Reglas sobre cómo CMD.EXE analiza los números
Para cualquiera que desee mejorar las reglas de análisis de cmd.exe, hay un tema de discusión en el foro DosTips donde se pueden informar problemas y hacer sugerencias.
Espero que ayude a
Jan Erik (jeb) - Autor original y descubridor de las fases
Dave Benham (dbenham) - Mucho contenido adicional y edición