Frage

Ich habe immer gefragt, wie Menschen in einer Befehlszeile eine vorherige Zeile aktualisieren. ein gutes Beispiel dafür ist, wenn der Befehl wget in Linux verwendet wird. Es erzeugt ein ASCII-Ladebalken von Sorten, die wie folgt aussehen:

  

[======>] 37%

und natürlich die Ladebalken bewegt und die prozentualen Veränderungen, aber es ist nicht eine neue Zeile machen. Ich kann nicht herausfinden, wie dies zu tun. Kann jemand mich in die richtige Richtung?

War es hilfreich?

Lösung

Es gibt zwei Möglichkeiten, die ich kenne, dies zu tun:

  • Verwenden Sie die Zurück-Escape-Zeichen ( '\ b') Ihre Zeile
  • löschen
  • Verwenden Sie das curses Paket, wenn Ihre Programmiersprache der Wahl hat Bindings für sie.

Und ein Google enthüllt ANSI-Escape-Codes , die ein guter Weg zu sein scheinen. Als Referenz hier ist eine Funktion in C ++, dies zu tun:

void DrawProgressBar(int len, double percent) {
  cout << "\x1B[2K"; // Erase the entire current line.
  cout << "\x1B[0E"; // Move to the beginning of the current line.
  string progress;
  for (int i = 0; i < len; ++i) {
    if (i < static_cast<int>(len * percent)) {
      progress += "=";
    } else {
      progress += " ";
    }
  }
  cout << "[" << progress << "] " << (static_cast<int>(100 * percent)) << "%";
  flush(cout); // Required.
}

Andere Tipps

Eine Möglichkeit, dies zu tun ist, um immer wieder die Textzeile mit dem aktuellen Fortschritt zu aktualisieren. Zum Beispiel:

def status(percent):
    sys.stdout.write("%3d%%\r" % percent)
    sys.stdout.flush()

Man beachte, daß I sys.stdout.write anstelle von print (dies ist Python), weil print automatisch prints "\ r \ n" (Wagenrücklauf new-line) am Ende jeder Zeile. Ich möchte nur die Wagenrücklauf, die den Cursor an den Anfang der Zeile zurückgibt. Auch die flush() notwendig sind, weil standardmäßig sys.stdout nur spült seinen Ausgang nach einem Newline (oder nach dem Puffer voll ist).

Das Geheimnis ist nur \ r statt \ n oder \ r \ n an den und der Zeile zu drucken.

\ r ist Wagenrücklauf genannt und bewegt den Cursor am Anfang der Zeile

\ n Zeilenvorschub genannt, und es bewegt den Cursor in der nächsten Zeile In der Konsole. Wenn Sie nur \ r verwenden Sie die zuvor geschriebenen Zeile überschrieben. So schreibt zunächst eine Zeile wie folgt:

[          ]

fügen Sie dann ein Zeichen für jede Zecke

\r[=         ]

\r[==        ]

...

\r[==========]

und so weiter. Sie können 10 Zeichen verwendet werden, die jeweils eine 10% entspricht. Auch, wenn Sie eine Meldung angezeigt werden soll, wenn Sie fertig, nicht vergessen auch genug weiße Zeichen hinzufügen, so dass Sie die zuvor geschrieben Gleichheitszeichen überschreiben wie folgt:

\r[done      ]

unten ist meine Antwort, verwenden Sie den Windows-API Konsolen (Windows) , Programmierung von C.

/*
* file: ProgressBarConsole.cpp
* description: a console progress bar Demo
* author: lijian <hustlijian@gmail.com>
* version: 1.0
* date: 2012-12-06
*/
#include <stdio.h>
#include <windows.h>

HANDLE hOut;
CONSOLE_SCREEN_BUFFER_INFO bInfo;
char charProgress[80] = 
    {"================================================================"};
char spaceProgress = ' ';

/*
* show a progress in the [row] line
* row start from 0 to the end
*/
int ProgressBar(char *task, int row, int progress)
{
    char str[100];
    int len, barLen,progressLen;
    COORD crStart, crCurr;
    GetConsoleScreenBufferInfo(hOut, &bInfo);
    crCurr = bInfo.dwCursorPosition; //the old position
    len = bInfo.dwMaximumWindowSize.X;
    barLen = len - 17;//minus the extra char
    progressLen = (int)((progress/100.0)*barLen);
    crStart.X = 0;
    crStart.Y = row;

    sprintf(str,"%-10s[%-.*s>%*c]%3d%%", task,progressLen,charProgress, barLen-progressLen,spaceProgress,50);
#if 0 //use stdand libary
    SetConsoleCursorPosition(hOut, crStart);
    printf("%s\n", str);
#else
    WriteConsoleOutputCharacter(hOut, str, len,crStart,NULL);
#endif
    SetConsoleCursorPosition(hOut, crCurr);
    return 0;
}
int main(int argc, char* argv[])
{
    int i;
    hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    GetConsoleScreenBufferInfo(hOut, &bInfo);

    for (i=0;i<100;i++)
    {
        ProgressBar("test", 0, i);
        Sleep(50);
    }

    return 0;
}

Powershell hat ein Write-Progress-Cmdlets, die eine in-Konsole Statusleiste erstellt, die Sie aktualisieren und ändern, wie das Skript ausgeführt wird.

Hier ist die Antwort auf Ihre Frage ... (Python)

def disp_status(timelapse, timeout):
  if timelapse and timeout:
     percent = 100 * (float(timelapse)/float(timeout))
     sys.stdout.write("progress : ["+"*"*int(percent)+" "*(100-int(percent-1))+"]"+str(percent)+" %")
     sys.stdout.flush()
     stdout.write("\r  \r")

Wenn Ihr eine Skriptsprache verwenden Sie den „tput cup“ Befehl verwenden, könnte dies zu tun bekommen ... P. S. Dies ist eine Linux / Unix Sache nur so weit, wie ich weiß ...

scroll top