Como sobrescrever a mesma linha na saída do comando do arquivo de lote

8

Eu quero escrever algumas informações de status que substituam a última linha quando eu faço alguma coisa.

No seguinte arquivo bat de exemplo, eu quero que o texto Step 2 sobrescreva Step 1 na mesma linha na saída do comando.

echo off

echo Step 1
REM Do some stuff...

echo Step 2
REM do some other stuff...
    
por awe 14.12.2009 / 08:16

5 respostas

5

Este script fará exatamente o que você pediu:

@echo off

setlocal enableextensions enabledelayedexpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "ASCII_13=%%a"

set /p "=Step 1" <NUL
REM Do some stuff...

set /p "=!ASCII_13!Step 2" <NUL
REM do some other stuff...

Encontrei essa resposta observando o código em uma biblioteca de manipulação de caracteres de script em lote gravada por Dave Benham chamada CharLib .

Esta biblioteca é capaz de criar todos os caracteres no intervalo 1..255.

Para mais informações, consulte o tópico "É possível converter um caractere ao seu valor ASCII? "

Edit 2017-4-26: Parece que o código acima não funciona mais . Não tenho certeza de quando esse comportamento teria mudado, mas definitivamente funcionava. O caractere CR após o = agora é removido pelo comando set . Ah, parece ser uma mudança na maneira como o set funciona entre o XP e versões posteriores do Windows. Veja a excelente resposta em Sobrescrever linha no arquivo de lote do Windows? (duplicado) para mais detalhes e exemplos de códigos extras.

Uma alternativa é colocar um caractere que não seja espaço em branco antes do !ASCII_13! e fazer com que ele seja apagado também, talvez inserindo também um backspace (que não é removido) seguido por um espaço ou anexando espaços para o final da string de prompt (que não são removidos).

Por exemplo assim:

@echo off

setlocal enableextensions enabledelayedexpansion
for /f %%a in ('copy /Z "%~dpf0" nul') do set "ASCII_13=%%a"

set /p "=Step 1" <NUL
REM Do some stuff...

set /p "=x!ASCII_13!Step 2 " <NUL
REM do some other stuff...
    
por 24.10.2012 / 12:57
6

Para responder à pergunta:

@echo off
CALL :EVALUATE "chr(8)"
SET backspace=%result%
<nul set /p =Step 1
:: DO SOME STUFF....
<nul set /p =%backspace%
<nul set /p =2
:: DO SOME OTHER STUFF....
<nul set /p =%backspace%%backspace%%backspace%%backspace%%backspace%%backspace%
<nul set /p =End   
GOTO:EOF



:EVALUATE           -- evaluate with VBS and return to result variable
::                  -- %~1: VBS string to evaluate
:: extra info: http://groups.google.com/group/alt.msdos.batch.nt/browse_thread/thread/9092aad97cd0f917

@IF [%1]==[] ECHO Input argument missing & GOTO :EOF 

@ECHO wsh.echo "result="^&eval("%~1") > %temp%\evaluate_tmp_67354.vbs 
@FOR /f "delims=" %%a IN ('cscript //nologo %temp%\evaluate_tmp_67354.vbs') do @SET "%%a" 
@DEL %temp%\evaluate_tmp_67354.vbs
::ECHO %result%
@GOTO:EOF

Saída:

End

Basicamente, o que o script faz, escreve Step 1 , volta a um lugar, sobrescreve 1 e, no final, volta completamente e sobrescreve Step 2 com End .

Esta volta eu faço com o caractere ASCII especial 8 que é backspace. Como não sei como escrevê-lo em cmd, uso a função: EVALUATE, que executa a função VBS Chr (), e coloca o caractere de backspace na variável result . Se alguém souber uma maneira melhor, por favor avise.

    
por 24.09.2012 / 20:22
3

Você não pode. Normalmente, você pode conseguir esse tipo de coisa incluindo um caractere de retorno de carro (0x0D) no arquivo que colocará o cursor de volta na primeira coluna na mesma linha. Mas neste caso não funciona; o CR é apenas comido em silêncio.

Além disso, obter o CR lá é meio complicado e pelo menos aqui envolveu um editor de texto. Eu sugiro que você escreva um pequeno programa utilitário que fará isso para você, na verdade não é muito difícil. O seguinte pequeno programa em C pode ser suficiente (se você não precisa de Unicode):

#include <stdio.h>

int main(int argc, char* argv[]) {
  if (argc < 2) return 1;
  printf("\r%s", argv[1]);
}

Ele não faz nada mais do que imprimir um caractere CR e, em seguida, o texto especificado como seu primeiro argumento. Uso da seguinte forma:

@echo off
<nul set /P X=Step 1
pause>nul 2>nul
over.exe "Step 2"

A última linha é a chamada para esse programa. A segunda linha é o idioma de lote normal para imprimir texto sem uma quebra de linha à direita (o que é importante neste caso, porque senão você não poderia sobrescrever a linha). Você poderia muito bem usar o programa acima, mas também nesse lugar.

Uma maneira levemente hacky, mas a única em que você pode ter certeza de onde vai acabar, é usar cls antes da saída do seu passo. Vai piscar, mas assim você sempre escreve no canto superior esquerdo. E espante tudo o que era visível no console (e é por isso que eu não recomendaria); a maioria dos usuários não gosta muito disso.

    
por 14.12.2009 / 08:54
1
@echo off
for /F "tokens=1 delims=# " %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do set "BSPACE=%%a"
<nul set /p =Step 1
ping 127.0.0.1 >nul
<nul set /p =%BSPACE%
<nul set /p =2
ping 127.0.0.1 >nul
<nul set /p =%BSPACE%
<nul set /p =3
ping 127.0.0.1 >nul
<nul set /p =%BSPACE%%BSPACE%%BSPACE%%BSPACE%%BSPACE%%BSPACE%
<nul set /p =End.  
pause

EXPLICAÇÃO:

for /F "tokens=1 delims=# " %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do set "BSPACE=%%a"

isto irá definir o caractere backspace na variável BSPACE. Agora, para ver o resultado, digite:

echo ab%BSPACE%c

saída: ac

você pode usar essa variável BSPACE mais de uma vez para excluir vários caracteres.

Agora, se você quiser definir um retorno de carro em uma variável, use

for /F "usebackq" %%a in ( copy / Z "% ~ dpf0" nul ) DO (set "cr=%%a")

para ver o resultado, digite: setlocal EnableDelayedExpansion & echo asfasdhlfashflkashflksa!CR!***

a saída será:      ***asfasdhlfashflkashflksa

@ a resposta de davour acima também é linda, mas a resposta de @ timfoden não funcionou para mim.

    
por 21.02.2015 / 18:07
0

Você precisaria de uma biblioteca de cursores de tela como curses ou ncurses , mas eu não sou muito familiarizado com o seu uso. Ambas as bibliotecas foram desenvolvidas para sistemas Unix, mas você pode encontrá-las no Windows (no ambiente Cygwin ou GnuWin32 ).

Eu não sei de nenhuma maneira fácil de acessá-los em um arquivo de lote no estilo DOS. Talvez seja melhor programar em uma linguagem compilada. Dê uma olhada no Ncurses HOWTO para ter uma idéia melhor de como será útil.

    
por 14.12.2009 / 09:09