unidades - windows batch file documentation




Por que o comando ECHO imprime algum espaço extra no arquivo? (2)

Estou lendo várias linhas de um arquivo de dados e anexei-o a outro arquivo. A questão é que algum espaço extra está no arquivo de saída no final das linhas anexadas. É obrigatório aparar o espaço à direita de acordo com a minha exigência, porque no arquivo de dados original não há espaço no final das linhas. Eu tentei todas as coisas possíveis, mas ainda não consigo fazer isso.

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

Opções que eu tentei:

  1. echo %%c>>temp_data.txt ... obtendo 1 espaço final da linha

  2. set lines=%%c
    echo !lines!>>temp_data.txt ... obtendo 1 espaço final da linha

  3. echo !lines:~0,-1!>>temp_data.txt ... última caractere da linha aparada

  4. set lines=!lines: =!
    echo !lines!>>temp_data.txt ... todos os espaços dentro da linha também são aparados (precisa aparar apenas o final da linha, que não está presente no arquivo de dados original)


Há um espaço à direita no final da linha de echo , como já escreveu, que não é ignorado pelo ECHO . Este espaço à direita também é produzido pelo ECHO após %%c .

Um redirecionamento geralmente é escrito no final de uma linha de comando, mas pode ser escrito em qualquer lugar. Também é possível escrever o redirecionamento no início como mostrado abaixo ou em algum lugar no meio, como pode ser visto na linha de comando FOR nesta resposta . A análise de uma linha de comando ECHO é diferente de todas as outras linhas de comando, pois um caractere de espaço fora de uma cadeia dupla não é interpretado como separador de argumentos e, portanto, cada caractere de espaço na linha de comando do ECHO é importante. como > .

Isso pode ser visto facilmente

  • criando um arquivo de lote apenas com o echo Test>Test.txt com um espaço à direita após Test.txt ,
  • abrindo uma janela de prompt de comando e
  • executando este arquivo em lote a partir da janela do prompt de comando.

A saída é echo Test 1>Test.txt . So > é substituído pelo interpretador de comandos do Windows por 1> (espaço, um, colchete angular direito) e adicionalmente movido para o final da linha. Este movimento na linha de comando do ECHO faz com que o espaço originalmente à esquerda seja movido para a esquerda após o texto Test e, portanto, também é produzido pelo ECHO .

Esta modificação na linha de comando durante o pré-processamento de todo o bloco de comandos também pode ser vista executando código de lote postado original sem @echo off de dentro de uma janela de prompt de comando para depurar o arquivo de lote. As saídas do interpretador de comandos do Windows com mydata.txt contendo a linha ú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

O espaço à direita depois de >>temp_data.txt é agora após o pré-processamento de toda a linha de comandos FOR com o bloco de comandos contendo apenas um único comando deixado para 1>>temp_data.txt . Quando FOR executa a linha de comando ECHO , o espaço à direita sendo agora um espaço adicional entre a linha lida de mydata.txt e 1>>temp_data.txt também é produzido pelo ECHO .

Deve sempre ser levado em conta o que é realmente executado pelo interpretador de comandos do Windows após o pré-processamento / análise de uma linha de comando e não o que está escrito no arquivo de lote.

Além disso, a expansão de variável de ambiente atrasada é ativada, o que resulta na leitura de linha do arquivo referenciado com %%c sendo processado pelo interpretador de comandos do Windows para !VariableName! antes de executar o comando ECHO . Tudo entre dois pontos de exclamação na linha é interpretado como nome da variável e, portanto, substituído pelo valor da variável referenciada, respectivamente, nada, se não houver tal variável de ambiente. Um único ponto de exclamação (restante) é simplesmente removido pelo interpretador de comandos do Windows durante esse processamento adicional da linha antes da execução do ECHO .

Solução 1:

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

A expansão de variável de ambiente atrasada é explicitamente desabilitada nesse código de lote para interpretar pontos de exclamação sempre como caracteres literais.

O arquivo de texto com a (s) linha (s) a ler é especificado usando a variável de ambiente predefinida USERPROFILE incluída entre aspas duplas para funcionar em qualquer computador com Windows. As aspas duplas requerem a opção usebackq para obter a cadeia do nome do arquivo com o caminho interpretado como nome do arquivo de texto a partir do qual as linhas devem ser lidas.

Como uma linha talvez termine com um número no intervalo de 1 a 9, não é bom usar:

echo %%c>>temp_data.txt

É melhor especificar o operador de redirecionamento no início da linha de comando do ECHO e especificar em seguida o echo %%c sem espaço à direita. Leia o artigo da Microsoft sobre o uso de operadores de redirecionamento de comandos para obter mais informações.

Por favor note que FOR ignora linhas vazias e também todas as linhas começando com um ponto e vírgula com as opções usadas. ; é o padrão para a opção eol (fim de linha) não especificado explicitamente neste arquivo de lote.

Ao executar este pequeno arquivo batch com @echo off modificado para @echo ON dentro de uma janela de prompt de comandos ao invés de clicar duas vezes nele, pode ser visto o interpretador de comandos do Windows realmente executado:

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

Assim, pode-se ver qual linha de comando é finalmente executada pelo interpretador de comandos do Windows após o pré-processamento de cada linha de comando do arquivo em lote antes da execução. >> foi substituído por 1>> (observe o espaço inserido no início) e o redirecionamento no início foi movido para o final da linha de comando do ECHO .

Solução 2:

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

O comando COPY pode ser usado para mesclar o conteúdo de vários arquivos especificados com o operador + em um único arquivo especificado por último. Esse recurso é usado aqui para anexar às linhas temp_data.txt existentes as linhas de mydata.txt na área de trabalho do usuário. A opção /B (dados binários) é necessária para evitar que o COPY seja temp_data.txt ao arquivo de saída temp_data.txt ^ Z, que é o caractere de controle substituto SUB com o valor de código hexadecimal 1A.

Esta solução é definitivamente melhor que a primeira, pois não importa qual seja o arquivo mydata.txt .

Para entender os comandos usados ​​e como eles funcionam, abra uma janela de prompt de comando, execute os seguintes comandos e leia com atenção todas as páginas de ajuda exibidas para cada comando.

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

Isso deve fazer o necessário, incluindo a necessidade de comentar a linha 100.

Um: não use expansão atrasada quando não for necessário.
Dois: Remova o espaço à direita do seu 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
)