windows batch-file

windows - ¿Por qué el comando ECHO imprime un espacio final adicional en el archivo?



batch-file (3)

Estoy leyendo varias líneas de un archivo de datos y lo agrego a otro archivo. El problema es que hay espacio extra en el archivo de salida al final de las líneas adjuntas. Es obligatorio recortar el espacio final de acuerdo con mis requisitos porque en el archivo de datos original no hay espacio al final de las líneas. Intenté todas las cosas posibles, pero todavía no puedo lograr esto.

@echo off setlocal enabledelayedexpansion FOR /F "delims=" %%c IN (C:/Users/184863/Desktop/mydata.txt) DO ( echo %%c>>temp_data.txt ) endlocal

Opciones que probé:

  1. echo %%c>>temp_data.txt ... obteniendo 1 espacio final de línea

  2. set lines=%%c
    echo !lines!>>temp_data.txt ... obteniendo 1 espacio final de línea

  3. echo !lines:~0,-1!>>temp_data.txt ... echo !lines:~0,-1!>>temp_data.txt último carácter de la línea

  4. set lines=!lines: =!
    echo !lines!>>temp_data.txt ... todos los espacios dentro de la línea también se recortan (es necesario recortar solo el final de la línea, que no está presente en el archivo de datos original)


Esto debería hacer lo necesario, incluida la necesidad de comentar la línea 100.

Uno: no utilice la expansión retrasada cuando no sea necesario.
Dos: elimine el espacio final en su comando echo.

@( SETLOCAL ECHO OFF SET "_File=C:/Users/184863/Desktop/mydata.txt" SET "_Count=" SET "_Comment=Your Special Comment " ) FOR /F "tokens=* delims=" %%c IN (%_File%) DO ( SET /A "Count+=1">NUL CALL ECHO.[%COUNT%] | FIND "[100]">NUL && ( ECHO:%_Comment%%~c ) || ( ECHO.%%c ) )>>"%~dp0temp_data.txt" REM Replace the original file with the commented File MOVE /Y "%~dp0temp_data.txt" "%_File%" ( ENDLOCAL EXIT /B 0 )


Hay un espacio final al final de la línea de echo como ya escribió que no es ignorado por ECHO . ECHO también genera este espacio final después de %%c .

Una redirección generalmente se escribe al final de una línea de comando, pero se puede escribir en cualquier lugar. También es posible escribir la redirección al principio como se muestra a continuación o en algún lugar en el medio, como se puede ver en la línea de comando FOR en esta respuesta . El análisis de una línea de comando de ECHO es diferente a todas las demás líneas de comando, ya que un carácter de espacio fuera de una cadena entre comillas dobles no se interpreta como un separador de argumentos y, por esa razón, cada carácter de espacio en la línea de comando de ECHO es importante y es emitido por ECHO, incluidos los anteriores a los operadores de redirección como > .

Esto se puede ver fácilmente por

  • crear un archivo por lotes con solo echo Test>Test.txt con un espacio final después de Test.txt ,
  • abrir una ventana de símbolo del sistema y
  • ejecutar este archivo por lotes desde la ventana del símbolo del sistema.

La salida es echo Test 1>Test.txt . Por lo tanto, > se reemplaza por el intérprete de comandos de Windows por 1> (espacio, uno, soporte de ángulo recto) y además se mueve al final de la línea. Este movimiento en la línea de comando de ECHO da como resultado que el espacio original se mueva hacia la izquierda después del texto Test y, por lo tanto, también es generado por ECHO .

Esta modificación de la línea de comandos durante el preprocesamiento de todo el bloque de comandos también se puede ver ejecutando el código de lote original publicado sin @echo off desde una ventana de símbolo del sistema para depurar el archivo por lotes. El intérprete de comandos de Windows genera mydata.txt contiene la línea única [code=119888#!198; ttps://egrul.nalog.ru/] [code=119888#!198; ttps://egrul.nalog.ru/] :

setlocal enabledelayedexpansion FOR /F "delims=" %c IN (C:/Users/184863/Desktop/mydata.txt) DO (echo %c 1>>temp_data.txt ) (echo [code=119888#!198; ttps://egrul.nalog.ru/] 1>>temp_data.txt ) endlocal

El espacio final después de >>temp_data.txt ahora es después de preprocesar toda la línea de comando FOR con el bloque de comando que contiene un solo comando a la izquierda para 1>>temp_data.txt . Cuando FOR ejecuta la línea de comandos de ECHO , el espacio final ahora es un espacio adicional entre la línea leída desde mydata.txt y 1>>temp_data.txt también es 1>>temp_data.txt por ECHO .

Siempre se debe tener en cuenta lo que realmente ejecuta el intérprete de comandos de Windows después de preprocesar / analizar una línea de comandos y no lo que está escrito en el archivo por lotes.

Además, la expansión de la variable de entorno retardada está habilitada, lo que da como resultado una lectura de línea del archivo al que se hace referencia con %%c procesado por el intérprete de comandos de Windows para !VariableName! antes de ejecutar el comando ECHO . Todo entre dos signos de exclamación en línea se interpreta como el nombre de la variable y, por lo tanto, se reemplaza por el valor de la variable referenciada, respectivamente, nada si no existe dicha variable de entorno. El intérprete de comandos de Windows simplemente elimina un signo de exclamación (restante) durante este procesamiento adicional de la línea antes de la ejecución de ECHO .

Solución 1:

@echo off setlocal EnableExtensions DisableDelayedExpansion for /F "usebackq delims=" %%I in ("%USERPROFILE%/Desktop/mydata.txt") do >>temp_data.txt echo %%I endlocal

La expansión de la variable de entorno retrasada se deshabilita explícitamente en este código de lote para interpretar los signos de exclamación siempre como caracteres literales.

El archivo de texto con la (s) línea (s) para leer se especifica usando la variable de entorno de Windows predefinida USERPROFILE entre comillas dobles para trabajar en cualquier computadora con Windows. Las comillas dobles requieren la opción usebackq para obtener la cadena del nombre del archivo con la ruta interpretada como el nombre del archivo de texto desde el cual leer las líneas.

Como una línea quizás termina con un número en el rango del 1 al 9, no es bueno usarla:

echo %%c>>temp_data.txt

Es mejor especificar el operador de redireccionamiento al comienzo de la línea de comando de ECHO y especificar a continuación el echo %%c sin espacio final. Lea el artículo de Microsoft sobre el uso de operadores de redirección de comandos para obtener más información.

Tenga en cuenta que FOR ignora las líneas vacías y también todas las líneas que comienzan con un punto y coma con las opciones utilizadas. ; es el valor predeterminado para la opción eol (final de línea) que no se especifica explícitamente en este archivo por lotes.

Al ejecutar este pequeño archivo por lotes con @echo off modificado a @echo ON desde una ventana de símbolo del sistema en lugar de hacer doble clic en él, se puede ver lo que el intérprete de comandos de Windows realmente ejecuta:

for /F "usebackq delims=" %I in ("C:/Users/184863/Desktop/mydata.txt") do echo %I 1>>temp_data.txt echo [code=119888#!198; ttps://egrul.nalog.ru/] 1>>temp_data.txt

Por lo tanto, se puede ver qué línea de comando finalmente ejecuta el intérprete de comandos de Windows después de preprocesar cada línea de comando del archivo por lotes antes de la ejecución. >> fue reemplazado por 1>> (observe el espacio insertado al comienzo) y la redirección al comienzo se movió al final de la línea de comando de ECHO .

Solución 2:

@echo off copy /B temp_data.txt+"%USERPROFILE%/Desktop/mydata.txt" temp_data.txt >nul

El comando COPIAR se puede usar para fusionar el contenido de varios archivos especificados con el operador + en un solo archivo especificado en último lugar. Esta característica se usa aquí para agregar a temp_data.txt las líneas existentes de mydata.txt en el escritorio del usuario. La opción /B (datos binarios) es necesaria para evitar que COPY se agregue al archivo de salida temp_data.txt ^ Z, que es el carácter de control sustituto SUB con el valor de código hexadecimal 1A.

Esta solución es definitivamente mejor que la primera, ya que no importa lo que contenga el archivo mydata.txt .

Para comprender los comandos utilizados y cómo funcionan, abra una ventana de símbolo del sistema, ejecute allí los siguientes comandos y lea con cuidado todas las páginas de ayuda que se muestran para cada comando.

  • copy /?
  • echo /?
  • endlocal /?
  • for /?
  • setlocal /?

Tiene un espacio de terminal en la línea echo %%c>>temp_data.txt (entre otros) que debe eliminarse. Esto es típico de la confusión que causan los espacios terminales.