Pertanyaan Bagaimana menganimasikan baris perintah?


Saya selalu bertanya-tanya bagaimana orang memperbarui baris sebelumnya di baris perintah. contoh yang bagus dari ini adalah ketika menggunakan perintah wget di linux. Ini menciptakan bar memuat ASCII macam yang terlihat seperti ini:

[======>] 37%

dan tentu saja loading bar bergerak dan perubahan persen, Tapi itu tidak membuat garis baru. Saya tidak tahu cara melakukan ini. Bisakah seseorang mengarahkan saya ke arah yang benar?


76
2017-09-13 00:53


asal


Jawaban:


Ada dua cara yang saya tahu untuk melakukan ini:

  • Gunakan karakter escape backspace ('\ b') untuk menghapus garis Anda
  • Menggunakan curses paket, jika bahasa pemrograman pilihan Anda memiliki bindings untuk itu.

Dan Google terungkap ANSI Escape Codes, yang tampaknya menjadi cara yang baik. Untuk referensi, berikut adalah fungsi dalam C ++ untuk melakukan ini:

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

42
2017-09-13 00:56



Salah satu cara untuk melakukan ini adalah secara berulang memperbarui baris teks dengan kemajuan saat ini. Sebagai contoh:

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

Perhatikan bahwa saya menggunakan sys.stdout.write dari pada print (ini Python) karena print secara otomatis mencetak "\ r \ n" (carriage-return new-line) di akhir setiap baris. Saya hanya ingin carriage-return yang mengembalikan kursor ke awal baris. Juga flush() diperlukan karena secara default, sys.stdout hanya flushes outputnya setelah newline (atau setelah buffer penuh).


56
2017-09-13 00:58



Rahasianya adalah hanya mencetak \ r bukan \ n atau \ r \ n pada baris dan.

disebut carriage return dan menggerakkan kursor di awal baris

\ n disebut feed baris dan memindahkan kursor ke baris berikutnya Di konsol. Jika Anda hanya menggunakan \ r Anda menimpa baris yang ditulis sebelumnya. Jadi pertama-tama tulis baris seperti berikut:

[          ]

lalu tambahkan tanda untuk setiap tick

\r[=         ]

\r[==        ]

...

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

dan seterusnya. Anda dapat menggunakan 10 karakter, masing-masing mewakili 10%. Juga, jika Anda ingin menampilkan pesan ketika selesai, jangan lupa untuk juga menambahkan karakter putih yang cukup sehingga Anda menimpa tanda sama yang ditulis sebelumnya seperti:

\r[done      ]

13
2017-10-06 15:04



di bawah ini adalah jawaban saya, gunakan windows APIKonsol (Windows), pengkodean 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;
}

4
2017-12-06 06:47



PowerShell memiliki cmdlet Tulis-Kemajuan yang membuat bar progres di-konsol yang dapat Anda perbarui dan ubah saat skrip Anda berjalan.


3
2017-09-13 01:10



Inilah jawaban atas pertanyaan Anda ... (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")

3
2017-07-04 09:12



Sebagai tindak lanjutnya Jawaban Greg, di sini adalah versi lengkap dari fungsinya yang memungkinkan Anda untuk menampilkan pesan multi-baris; masukkan saja daftar atau tupel string yang ingin Anda tampilkan / perbarui.

def status(msgs):
    assert isinstance(msgs, (list, tuple))

    sys.stdout.write(''.join(msg + '\n' for msg in msgs[:-1]) + msgs[-1] + ('\x1b[A' * (len(msgs) - 1)) + '\r')
    sys.stdout.flush()

Catatan: Saya hanya menguji ini menggunakan terminal linux, sehingga jarak tempuh Anda dapat bervariasi pada sistem berbasis Windows.


2
2018-06-23 22:44



Jika Anda menggunakan bahasa scripting Anda bisa menggunakan perintah "tput cup" untuk menyelesaikannya ... P.S. Ini adalah Linux / Unix hanya sejauh yang saya tahu ...


0
2017-10-24 18:55