So überschreiben Sie dieselbe Zeile in der Befehlsausgabe der Batchdatei

13

Ich möchte einige Statusinformationen schreiben, die die letzte Zeile ersetzen, wenn ich etwas tue.

In der folgenden Beispiel-Bat-Datei soll der Text Step 2in Step 1derselben Zeile in der Befehlsausgabe überschrieben werden.

echo off

echo Step 1
REM Do some stuff...

echo Step 2
REM do some other stuff...
Scheu
quelle

Antworten:

8

Dieses Skript macht genau das, was Sie gefragt haben:

@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...

Ich fand diese Antwort, indem ich mir den Code in einer von Dave Benham geschriebenen Batch-Skript-Zeichenmanipulationsbibliothek namens CharLib ansah .

Diese Bibliothek kann alle Zeichen im Bereich 1..255 erstellen.

Weitere Informationen finden Sie im Thread mit dem Titel "Ist es möglich, ein Zeichen in seinen ASCII-Wert zu konvertieren?"

Edit 2017-4-26: Es scheint, dass der obige Code nicht mehr funktioniert . Ich bin mir nicht sicher, wann sich dieses Verhalten geändert hätte, aber es hat definitiv funktioniert. Das CRZeichen nach dem =Jetzt wird vom setBefehl entfernt. Ah, es scheint eine Änderung in der Funktionsweise setzwischen XP und späteren Windows-Versionen zu sein. Sehen Sie die hervorragende Antwort in der Zeile Überschreiben in der Windows-Batchdatei? (Duplikat) für weitere Details und zusätzliche Codebeispiele.

Eine Alternative besteht dann darin, ein Nicht-Leerzeichen vor das zu setzen !ASCII_13!und dafür zu sorgen, dass es auch gelöscht wird, möglicherweise entweder durch Einfügen eines Rückzeichens (das nicht entfernt wird) gefolgt von einem Leerzeichen oder durch Anhängen von Leerzeichen an das Ende des Eingabeaufforderungszeichenfolge (die nicht entfernt werden.)

ZB so:

@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...
timfoden
quelle
2
Für mich wird nur "Schritt 1Schritt 2" gedruckt, anstatt nur "Schritt 2" auf dem Bildschirm anzuzeigen.
Galmok
@galmok Das ist mir auch schon passiert, aber ich bin mir sicher, dass es nie früher passiert ist (da ich ein Skript habe, das in letzter Zeit perfekt funktioniert hat, hat sich das von Ihnen beschriebene Verhalten geändert.) Es scheint, dass der setBefehl jetzt alle entfernt CR- und LF-Zeichen (sowie Leerzeichen) nach dem =. Versuchen Sie, ein Nicht-Leerzeichen zwischen das =und das!ACSII_13!
timfoden
Es gibt eine Möglichkeit, all dies zu tun ... Ich bin tatsächlich gekommen, um zu sehen, ob jemand anderes es bemerkt hat, weil ich sehen wollte, ob er herausgefunden hat, wie weit es gegangen ist. ... Kann ich eine ANTWORT auf Stapelüberlauf schreiben? ODER .. wie eine Frage und sofort beantworten? Ich nehme an, ich könnte es in Frage stellen, was Sie damit machen könnten. Ich muss etwas essen gehen, aber ich werde dies mit einem Link für Sie aktualisieren.
Brent Rittenhouse
Schreiben Sie! ASCII_13! Nach Schritt 1, um das Abisolieren zu verhindern, würden Sie in Schritt 2 Folgendes codieren:set /p "=Step 2 " <NUL
Zimba
6

Um die Frage zu beantworten:

@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

Ausgabe:

End

Grundsätzlich schreibt das Skript, Step 1geht dann eine Stelle zurück, überschreibt 1und überschreibt am Ende vollständig und überschreibt Step 2mit End.

Dies gehe ich mit dem speziellen ASCII-Zeichen 8 zurück, das die Rücktaste ist. Da ich nicht weiß, wie man es in cmd schreibt, verwende ich die Funktion: EVALUATE, mit der die Funktion VBS Chr () ausgeführt wird, und füge das Rücktastezeichen in die Variable ein result. Wenn jemand einen besseren Weg kennt, beraten Sie bitte.

Davor Josipovic
quelle
1
In PowerShell können Sie auch $host.ui.RawUI.CursorPositionin einer Variablen speichern und später wiederherstellen, damit der Cursor an die Stelle zurückspringt, an der Sie sich befanden, und Ihre Ausgabe überschreibt. Nur eine Option für die Powershell, aber vielleicht ein bisschen sauberer als Ihre VBS Sachen sein :-)
mihi
4
@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

ERLÄUTERUNG:

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

Dadurch wird das Rücktastezeichen in die BSPACE-Variable gesetzt. Geben Sie nun Folgendes ein, um das Ergebnis anzuzeigen:

echo ab%BSPACE%c

Ausgabe: ac

Sie können diese BSPACE-Variable mehrmals verwenden, um mehrere Zeichen zu löschen.

Wenn Sie jetzt einen Wagenrücklauf in einer Variablen festlegen möchten, verwenden Sie

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

Geben Sie Folgendes ein, um das Ergebnis anzuzeigen: setlocal EnableDelayedExpansion & echo asfasdhlfashflkashflksa!CR!***

Die Ausgabe lautet: ***asfasdhlfashflkashflksa

Die Antwort von @ davour oben ist auch wunderschön, aber die Antwort von @ timfoden hat bei mir nicht funktioniert.

Sourav Ghosh
quelle
@ timfodens Antwort hat nicht funktioniert, weil! CR! sollte am Ende des vorherigen Schritts gehen. Anstelle all dieser% BSPACE% s könnten Sie auch! CR! und mit Leerzeichen füllen:set /p "=.!CR!End. " <NUL&echo:
Zimba
3

Das kannst du nicht. Normalerweise können Sie dies erreichen, indem Sie ein Wagenrücklaufzeichen (0x0D) in die Datei aufnehmen, wodurch der Cursor wieder auf die erste Spalte in derselben Zeile gesetzt wird. Aber in diesem Fall funktioniert es nicht; Die CR wird nur still gegessen.

Darüber hinaus ist es etwas schwierig, die CR dort hinein zu bringen, und zumindest hier ist ein Texteditor beteiligt. Ich würde vorschlagen, dass Sie ein kleines Hilfsprogramm schreiben, das dies für Sie erledigt. Es ist eigentlich nicht sehr schwer. Das folgende kleine C-Programm könnte ausreichen (wenn Sie keinen Unicode benötigen):

#include <stdio.h>

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

Es wird lediglich ein CR-Zeichen und dann der von Ihnen als erstes Argument angegebene Text gedruckt. Verwendung wie folgt:

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

Die letzte Zeile ist der Aufruf dieses Programms. Die zweite Zeile ist die normale Stapelsprache zum Drucken von Text ohne Zeilenumbruch (was in diesem Fall wichtig ist, da Sie die Zeile sonst nicht überschreiben könnten). Sie können das obige Programm aber auch an dieser Stelle verwenden.

Ein leicht hackiger Weg, aber der einzige, bei dem Sie sicher sein können, wo Sie landen, ist die Verwendung clsvor Ihrer Schrittausgabe. Flackert aber so schreibst du immer nach links oben. Und alles blockieren, was in der Konsole sichtbar war (weshalb ich es nicht empfehlen würde); Die meisten Benutzer mögen das nicht so sehr.

Joey
quelle
OK, ich hatte den Verdacht, dass es mit einer sauberen Kommandozeile nicht möglich war. Wenn ich ein Dienstprogramm dazu bringen möchte, kann ich das Ganze genauso gut in ein Dienstprogramm einfügen. Was ich wirklich wollte, war nur ein sichtbarer Countdown, der 5 Sekunden wartet und jede Sekunde herunterzählt, bis er fertig ist.
Ehrfurcht
4
Ehrfurcht: Wenn Sie unter Vista oder höher sind, timeout 5wird es funktionieren.
Joey
Groß! Danke! Timeout 5 funktioniert!
Ehrfurcht
4
Ich hätte meine eigentliche Ausgabe zum ersten Mal veröffentlichen sollen ...
Ehrfurcht
Natürlich kannst du; Fügen Sie einfach den Wagenrücklauf nach Schritt 1 hinzu! Darüber hinaus ist hier ein Code, um Wagenrücklauf ohne Texteditor zu erhalten:for /f %%a in ('copy /Z "%~f0" nul') do set "CR=%%a"
Zimba
1

Holen Sie sich das Zeilenumbruchzeichen, schreiben Sie den nächsten Schritt, kehren Sie zum Zeilenanfang zurück und schreiben Sie die nächste Zeile:

@echo off
cls
setlocal enabledelayedexpansion
echo Here's how it's done:

for /f %%a in ('copy /Z "%~f0" nul') do set "Newline=%%a"
set /p "=Step 1!Newline!" <NUL
REM Do some stuff...
ping -n 2 localhost > nul
set /p "=Step 2!Newline!" <NUL
ping -n 2 localhost > nul
set /p "=Step 3 " <NUL
REM do some other stuff...
ping -n 2 localhost > nul
echo:
echo Done.
Zimba
quelle
Dies funktioniert nur, wenn Step 1 Step 2 Step 3alle gleich lang sind. Wenn nicht, set /pbleibt der Text des ersten erhalten . Ich bin mir nicht sicher, wie ich das beheben soll.
Ste
Dieses Problem kann behoben werden, indem in der nächsten Eingabeaufforderung zusätzliche Leerzeichen verwendet werden. um alle vorherigen Zeichen abzudecken. Beispiel set /p "=Step 2SPACESPACESPACESPACE!Newline!" <NUL im Gegensatz zu set /p "=Step 2!Newline!" <NUL. Tauschen Sie SPACEgegen den Charakter.
Ste
Wenn die vorherigen Zeilen länger sind, fügen Sie Leerzeichen hinzu, um zusätzliche Zeichen auszublenden, oder die Rücktaste vom Zeilenende bis zum Anfang oder nur die Rücktaste für die zusätzlichen Zeichen.
Zimba
0

Sie würden eine Bildschirm-Cursor-Bibliothek wie cursesoder benötigen ncurses, aber ich bin mit deren Verwendung nicht allzu vertraut. Beide Bibliotheken wurden für Unix-Systeme entwickelt, aber Sie können sie für Windows finden (in der Cygwin-Umgebung oder GnuWin32 ).

Ich kenne keine einfache Möglichkeit, in einer Batch-Datei im DOS-Stil darauf zuzugreifen. Sie sind möglicherweise besser dran, in einer kompilierten Sprache zu programmieren. Schauen Sie sich das Ncurses HOWTO an, um eine bessere Vorstellung davon zu bekommen, ob es nützlich sein wird.

Quacksalber
quelle
Flüche sind so ziemlich nur für Terminals und Terminalemulatoren. Sie sind nicht wirklich der nativen Konsolen-API von Windows zugeordnet.
Joey
KEINE Notwendigkeit für externe Bibliotheken; funktioniert gut mit CMD-Tools.
Zimba
0

Lösung 1

Mit Notepad ++ ist es möglich, das Backspace ←Zeichen (ASCII 0x08) direkt über das Einfügefeld für ASCII-Codes (Bearbeiten> Zeichenfeld) einzufügen .

Meine Lösung besteht darin, das [BS]Zeichen direkt einzufügen und es dann wie andere hier veröffentlichte Lösungen mehrmals zu verwenden, um vorherige Zeichen zu löschen:

Code

@ECHO OFF

SET "BACKSPACE_x7=[BS][BS][BS][BS][BS][BS][BS]"

SET /P "DUMMY_VAR=Step 1" < NUL
REM Do some stuff...

SET /P "DUMMY_VAR=%BACKSPACE_x7%Step 2" < NUL
REM Do some other stuff...

GOTO :EOF

Notepad ++ Screenshot

Windows-Batch-Überschreiben


Ausgabe

CMD-Ausgabe


Lösung 2

Eine andere Möglichkeit besteht darin, cecho (Echo-Befehl mit Farbunterstützung ) zu verwenden, um Carriage Return ↵ein Unicode-Zeichen (U + 000D) einzufügen:

Code

@ECHO OFF

SET CARRIAGE_RETURN={\u000D}

cecho Step 1
REM Do some stuff...

cecho %CARRIAGE_RETURN%Step 2
REM Do some other stuff...

GOTO :EOF

NB: cecho_x64.exeLäuft auf meinem Computer deutlich schneller als cecho.exe.

Andronoid
quelle