如何动画命令行?
我一直想知道人们如何更新命令行中的上一行。一个很好的例子就是在linux中使用wget命令。它创建各种各样的ASCII加载条看起来像这样:如何动画命令行?
[======> ] 37%
当然还有loa丁棒移动和百分比变化,但它并没有形成一个新的线。我无法弄清楚如何做到这一点。有人能指引我朝着正确的方向吗?
有两种方法,我知道要做到这一点:
- 用退格转义字符(“\ B”)删除您的线路
- 使用
curses
包,如果您选择的编程语言对它有约束力。
而谷歌透露ANSI Escape Codes,这似乎是一个好方法。作为参考,在这里是在C++函数来做到这一点:
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.
}
的一种方式做,这是反复更新的文本与当前进度行。例如:
def status(percent):
sys.stdout.write("%3d%%\r" % percent)
sys.stdout.flush()
注意,我使用的sys.stdout.write
代替print
(这是Python的),因为print
自动打印为“\ r \ n”个(回车换行)在每一行的末尾。我只是想要返回光标回到行的开始。此外,flush()
是必要的,因为默认情况下,sys.stdout
只在换行符后(或其缓冲区满了之后)刷新其输出。
和'c'中的printf和'\ r'一样。 – 2008-09-13 01:21:49
`flush()`后面到底是什么“刷新”?只是好奇... – Nearoo 2017-02-04 00:43:43
@Nearoo通常stdout缓冲其输出,直到写入换行符(\ n)。冲洗使局部线条立即出现。 – 2017-02-04 02:36:33
PowerShell有一个Write-Progress cmdlet,它可以创建一个控制台内进度条,您可以在脚本运行时更新和修改该进度条。
如果您使用脚本语言,您可以使用“tput cup”命令来完成此操作... P.S.这是在Linux/Unix的东西只就我所知...
作为后续行动,以Greg's answer,这里是他的功能的扩展版,它允许您显示多行消息;只需传入要显示/刷新的字符串的列表或元组即可。
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()
注:我这使用的是Linux终端,所以你的里程可能会在基于Windows的系统只改变测试。
这里是你的问题的答案......(蟒蛇)
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")
就是我的回答,使用Windows API Consoles(Windows),C的编码
/*
* file: ProgressBarConsole.cpp
* description: a console progress bar Demo
* author: lijian <[email protected]>
* 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;
}
秘密是只打印\ r而不是\ n或\ r \ n在行和行。
\ r被称为回车和它在该行
\ n被称为换行的开始移动光标并将其移动光标到下一行 在控制台。如果您仅使用\ r覆盖先前写入的行。 所以先写类似下面的一行:
[ ]
然后加了个手势,每个刻度
\r[= ]
\r[== ]
...
\r[==========]
等。 您可以使用10个字符,每个字符代表10%。 另外,如果你想在完成时显示一条消息,不要忘了,让你覆盖以前写等号像这样还补充足够的白色字符:
\r[done ]
假设他正在一个Win32控制台应用程序(不DOS)在最新版本的Windows上(即2000+),ANSI转义码完全不起作用。正如您链接到的维基百科文章所述。 – 2008-09-25 02:58:46
如果在Windows上使用ANSI Escape Sequences,则可以使用Ansicon。 https://github.com/adoxa/ansicon – 2014-12-17 19:42:17