¿Qué estilo de comentario debo usar en los archivos por lotes?


He estado escribiendo algunos archivos por lotes, y me encontré con esta guía del usuario , que ha sido bastante informativa. Una cosa que me mostró fue que las líneas se pueden comentar no solo con REM, sino también con ::. Dice:

Los comentarios en el código por lotes se pueden hacer usando dos puntos, esto es mejor que usar el comando REM porque las etiquetas se procesan antes de los símbolos de redirección. ::<remark> no causa problemas, pero rem <remark> produce errores.

¿Por qué entonces, hacer la mayoría guías y ejemplos que veo usar el comando REM? :: Funciona en todas las versiones de Windows?

Author: MikeFHay, 2012-09-13

9 answers

Tl; dr: REM es la forma documentada y compatible de incrustar comentarios en archivos por lotes.


:: es esencialmente una etiqueta en blanco a la que nunca se puede saltar, mientras que REM es un comando real que simplemente no hace nada. En ninguno de los casos (al menos en Windows 7) la presencia de operadores de redirección causa un problema.

Sin embargo, :: se sabe que se comporta mal en bloques bajo ciertas circunstancias, siendo analizado no como una etiqueta sino como una especie de letra de unidad. Estoy un poco confuso sobre dónde exactamente, pero eso solo es suficiente para hacerme usar REM exclusivamente. Es la forma documentada y soportada de incrustar comentarios en archivos por lotes, mientras que :: es simplemente un artefacto de una implementación en particular.


Aquí hay un ejemplo donde :: produce un problema en un bucle FOR.

En Este ejemplo no trabajo en un archivo llamado test.bat en su escritorio:

@echo off
for /F "delims=" %%A in ('type C:\Users\%username%\Desktop\test.bat') do (
    ::echo hello>C:\Users\%username%\Desktop\text.txt
)
pause

Mientras que este ejemplo funcionará como un comentario correctamente:

@echo off
for /F "delims=" %%A in ('type C:\Users\%username%\Desktop\test.bat') do (
    REM echo hello>C:\Users\%username%\Desktop\text.txt
)
pause

El problema parece ser cuando se intenta redirigir la salida a un archivo. Mi mejor conjetura es que está interpretando :: como una etiqueta escapada llamada :echo.

 310
Author: Joey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-03 14:44:31

Comentarios con REM

Un REM puede remarcar una línea completa, también una línea múltiple al final de la línea, si no es el final del primer token.

REM This is a comment, the caret is ignored^
echo This line is printed

REM This_is_a_comment_the_caret_appends_the_next_line^
echo This line is part of the remark

REM seguido de algunos caracteres .:\/= funciona un poco diferente, no comenta un ampersand, por lo que puede usarlo como comentario en línea.

echo First & REM. This is a comment & echo second

Pero para evitar problemas con archivos existentes como REM, REM.bat o REM;.bat solo debe utilizarse una variante modificada.

REM^;<space>Comment

Y para el carácter ; es también permitido uno de ;,:\/=

REM es aproximadamente 6 veces más lento que :: (probado en Win7SP1 con 100000 líneas de comentarios).
Para un uso normal no es importante (58µs frente a 360µs por línea de comentario)

Comentarios con ::

A :: siempre ejecuta un extremo de línea.

:: This is also a comment^
echo This line is also a comment

Etiquetas y también la etiqueta de comentario :: tener una lógica especial entre paréntesis bloques.
Se extienden siempre dos líneas ASÍ que: goto comando no trabajando .
Por lo tanto, no se recomiendan para bloques de paréntesis, ya que a menudo son la causa de errores de sintaxis.

Con ECHO ON se muestra una línea REM, pero no una línea comentada con ::

Ambos realmente no pueden comentar el resto de la línea, por lo que un simple %~ causará un error de sintaxis.

REM This comment will result in an error %~ ...

Pero REM es capaz de detener el analizador por lotes en una fase temprana, incluso antes de que se realice la fase de caracteres especiales.

@echo ON
REM This caret ^ is visible

Puede utilizar &REM o & :: para añadir un comentario al final de la línea de órdenes. Este enfoque funciona porque ' & ' introduce un nuevo comando en la misma línea.

Comentarios con signos de porcentaje % = comentario = %

Existe un estilo de comentario con signos de porcentaje.

En realidad estas son variables pero se expanden a la nada.
Pero la ventaja es que se pueden colocar en la misma línea, incluso sin &.
El signo igual asegura, que tal variable no puede existir.

echo Mytest
set "var=3"     %= This is a comment in the same line=%

El estilo de porcentaje se recomienda para macros por lotes, ya que no cambia el comportamiento del tiempo de ejecución, ya que el comentario se eliminará cuando se defina la macro.

set $test=(%\n%
%=Start of code=% ^
echo myMacro%\n%
)
 147
Author: jeb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:22

Después de darme cuenta de que podía usar label :: para hacer comentarios y comentar el código REM simplemente me pareció feo. Como se ha mencionado, el doble dos puntos puede causar problemas cuando se usa dentro de () código bloqueado, pero he descubierto una solución alternativa alternando entre las etiquetas :: y :espacio

:: This, of course, does
:: not cause errors.

(
  :: But
   : neither
  :: does
   : this.
)

No es feo como REM, y en realidad añade un poco de estilo a su código.

Así que fuera de los bloques de código uso :: y dentro de ellos alterno entre :: y :.

Por cierto, para grandes porciones de comentarios, como en el encabezado de su archivo por lotes, puede evitar comandos especiales y caracteres completamente simplemente gotoing sobre sus comentarios. Esto le permite usar cualquier método o estilo de marcado que desee, a pesar de que si CMD alguna vez intentó procesar esas líneas, lanzaría un silbido.

@echo off
goto :TopOfCode

=======================================================================
COOLCODE.BAT

Useage:
  COOLCODE [/?] | [ [/a][/c:[##][a][b][c]] INPUTFILE OUTPUTFILE ]

Switches:
       /?    - This menu
       /a    - Some option
       /c:## - Where ## is which line number to begin the processing at.
         :a  - Some optional method of processing
         :b  - A third option for processing
         :c  - A forth option
  INPUTFILE  - The file to process.
  OUTPUTFILE - Store results here.

 Notes:
   Bla bla bla.

:TopOfCode
CODE
.
.
.

Usa cualquier notación que desees *'s, @'s etc.

 24
Author: James K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-17 09:54:04

Otra alternativa es expresar el comentario como una expansión variable que siempre se expande a nada.

Los nombres de variables no pueden contener =, excepto para variables dinámicas no documentadas como
%=ExitCode% y %=C:%. Ningún nombre de variable puede contener un = después de la 1ª posición. Así que a veces uso lo siguiente para incluir comentarios dentro de un bloque entre paréntesis:

::This comment hack is not always safe within parentheses.
(
  %= This comment hack is always safe, even within parentheses =%
)

También es un buen método para incorporar comentarios en línea

dir junk >nul 2>&1 && %= If found =% echo found || %= else =% echo not found

El principal = es no es necesario, pero me gusta si por la simetría.

Hay dos restricciones:

1) el comentario no puede contener %

2) el comentario no puede contener :

 24
Author: dbenham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-23 11:20:34

Esta respuesta intenta un resumen pragmático de las muchas grandes respuestas en esta página: {[51]]}

la gran respuesta de jeb merece una mención especial, porque realmente va en profundidad y cubre muchos casos extremos.
En particular, señala que una referencia de variable/parámetro mal construida como %~ puede romper cualquier de las soluciones a continuación, incluidas las líneas REM .


Toda la línea comentarios - el único directamente estilo soportado:

  • REM (o variaciones de caso del mismo) es el único constructo de comentario oficial , y es la opción más segura - ver la respuesta útil de Joey.

  • :: es ampliamente utilizado) hack, que tiene pros y los contras:

    • Pros:

    • Cons :

      • Dentro de los bloques (...), :: puede romper el comando, y las reglas para un uso seguro son restrictivas y no son fáciles de recordar - ver más abajo.

Si usted quieres usar ::, usted tiene estas opciones:

  • Ya sea: Para estar seguro, haga una excepción dentro de (...) bloques y use REM allí, o no coloque comentarios dentro (...) en total.
  • O : Memorice las reglas dolorosamente restrictivas para el uso seguro de :: dentro (...), que se resumen en el siguiente fragmento:
@echo off

for %%i in ("dummy loop") do (

  :: This works: ONE comment line only, followed by a DIFFERENT, NONBLANK line.
  date /t

  REM If you followed a :: line directly with another one, the *2nd* one
  REM would generate a spurious "The system cannot find the drive specified."
  REM error message and potentially execute commands inside the comment.
  REM In the following - commented-out - example, file "out.txt" would be
  REM created (as an empty file), and the ECHO command would execute.
  REM   :: 1st line
  REM   :: 2nd line > out.txt & echo HERE

  REM NOTE: If :: were used in the 2 cases explained below, the FOR statement
  REM would *break altogether*, reporting:
  REM  1st case: "The syntax of the command is incorrect."
  REM  2nd case: ") was unexpected at this time."

  REM Because the next line is *blank*, :: would NOT work here.

  REM Because this is the *last line* in the block, :: would NOT work here.
)

Emulación de otros estilos de comentario - en línea y multilínea:

Tenga en cuenta que ninguno de estos estilos son soportados directamente por el lenguaje por lotes, pero pueden ser emulados.


Comentarios en línea:

* Los fragmentos de código a continuación usan ver como sustituto de un comando arbitrario, para facilitar la experimentación.
* Para hacer que los comandos SET funcionen correctamente con comentarios en línea, comilla dos veces la parte name=value; por ejemplo, SET "foo=bar".[1]

En este contexto puede distinguir dos subtipos:

  • EOL comments ([to-the-]end-of-line), que se puede colocar después de un comando, e invariablemente se extiende hasta el final de la línea (de nuevo, cortesía de la respuesta de jeb):

    • ver & REM <comment> aprovecha el hecho de que REM es un comando válido y & se puede usar para colocar un comando adicional después de uno existente.
    • ver & :: <comment> también funciona, pero es realmente solo utilizable fuera de (...) bloques, debido a que su uso seguro allí es aún más limitado que el uso de :: independiente.
  • Comentarios intra-line, que se colocan entre múltiples comandos en una línea o idealmente incluso dentro de de un comando dado.
    Los comentarios intra-line son la forma más flexible (de una sola línea) y pueden, por definición, utilizarse también como comentarios de fin de vida.

    • ver & REM^. ^<comment^> & ver permite insertar un comentario entre los comandos (de nuevo, cortesía de la respuesta de jeb), pero note cómo < y > necesitaban ser ^-escapadas, porque los siguientes caracteres. no se puede utilizar tal cual: < > | (mientras que unescaped & o && o || iniciar el siguiente comando).

    • %= <comment> =%, como se detalla en la gran respuesta de dbenham, es la forma más flexible, porque se puede colocar dentro de un comando (entre los argumentos).
      Se aprovecha de sintaxis de expansión variable de una manera que asegura que la expresión siempre se expande a la cadena vacía - mientras el texto del comentario no contenga ni % ni :
      Like REM, %= <comment> =% funciona bien tanto fuera como dentro de los bloques (...), pero es más distintivo visualmente; los únicos inconvenientes son que es más difícil de escribir, más fácil de equivocarse sintácticamente, y no es ampliamente conocido, lo que puede dificultar la comprensión del código fuente que utiliza el técnica.


Multi-line (bloque de línea completa) comentarios :

  • La respuesta de James K muestra cómo usar un goto declaración y una etiqueta para delimitar un comentario multilínea de longitud y contenido arbitrarios (que en su caso utiliza para almacenar información de uso).

  • La respuesta de Zee muestra cómo usar una "etiqueta nula" para crear un comentario multilínea, aunque debe tener cuidado tomado para terminar todas las líneas interiores con ^.

  • La entrada del blog de Rob van der Woude menciona otra opción algo oscura que le permiteend un archivo con un número arbitrario de líneas de comentario : An abrir ( solo hace que todo lo que viene después sea ignorado, siempre y cuando no contenga un ( non-^-escaped) ), es decir, siempre y cuando el bloque no esté cerrado.


[1] Usar SET "foo=bar" para definir variables - es decir, poner comillas dobles alrededor del nombre y = y el valor combinado - es necesario en comandos como SET "foo=bar" & REM Set foo to bar., para asegurarse de que lo que sigue a el valor de variable deseado (hasta el siguiente comando, en este caso un solo espacio) no se convierta accidentalmente en parte de él.
(Como un aparte: SET foo="bar" no solo no evitaría el problema, haría las comillas dobles parte del valor).
Tenga en cuenta que este problema es inherente a SET e incluso se aplica a accidental al final del espacio en blanco después del valor, por lo que es aconsejable siempre usar el enfoque SET "foo=bar".

 14
Author: mklement0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:10

Esta página dice que usar":: "será más rápido bajo ciertas restricciones Solo una cosa a considerar al elegir

 7
Author: mishal153,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-14 13:32:15

Buena pregunta... He estado buscando esta funcionalidad durante mucho tiempo también...

Después de varias pruebas y trucos parece que la mejor solución es la más obvia...

} > la mejor manera que encontré de hacerlo, evitando que la integridad del analizador falle, es reutilizando REM:

echo this will show until the next REM &REM this will not show

También puede usar multilínea con el truco "ETIQUETA NULA"... (no olvide el ^ al final de la línea para la continuidad)

::(^
this is a multiline^
comment... inside a null label!^
dont forget the ^caret at the end-of-line^
to assure continuity of text^ 
)
 4
Author: ZEE,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-03 21:24:50

James K, siento haberme equivocado en una buena parte de lo que dije. La prueba que hice fue la siguiente:

@ECHO OFF
(
  :: But
   : neither
  :: does
   : this
  :: also.
)

Esto cumple con su descripción de alternar pero falla con un ") fue inesperado en este momento."mensaje de error.

Hice algunas pruebas más hoy y descubrí que alternar no es la clave, pero parece que la clave es tener un número par de líneas, no tener dos líneas en una fila que comiencen con dos puntos (::) y no terminen en dos puntos. Considere la siguiente:

@ECHO OFF
(
   : But
   : neither
   : does
   : this
   : cause
   : problems.
)

Esto funciona!

Pero también considere esto:

@ECHO OFF
(
   : Test1
   : Test2
   : Test3
   : Test4
   : Test5
   ECHO.
)

La regla de tener un número par de comentarios no parece aplicarse cuando termina en un comando.

Desafortunadamente, esto es lo suficientemente complicado como para no estar seguro de querer usarlo.

Realmente, la mejor solución, y la más segura que se me ocurre, es si un programa como Notepad++ leería REM como dos puntos y luego escribiría dos puntos como sentencias REM cuando el archivo es guardado. Pero no estoy al tanto de un programa de este tipo y no estoy al tanto de cualquier plugins para Notepad++ que hace eso tampoco.

 3
Author: Darin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-26 19:39:27

Una discusión muy detallada y analítica sobre el tema está disponible en ESTA página

Tiene los códigos de ejemplo y los pros/contras de diferentes opciones.

 2
Author: BiLaL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-31 08:31:48