如何更改终端上一行的内容而不是编写新行?

fou*_*ric 28 terminal

因此,当wget获取网页时,它会向您显示一个状态栏,指示下载了多少文件。它看起来像这样:

25%[=============>______________________________________] 25,000 100.0K/s (下划线是空格;我只是不知道如何在其中获得多个连续的空格)

但是,它不是将另一行写入 stdout 并添加另一个进度条,而是更新它,如下所示:

50%[===========================>________________________] 50,000 100.0K/s

wget也不是唯一的例子。例如,当您通过管道输入某些内容less然后退出时,您的原始提示仍然存在,以及您之前运行的任何命令的结果。就像你从未离开过一样。

所以,我的问题是,这叫什么,我如何实现它,它一次只能用于一行,我可以在 C 中使用它吗?

Ulr*_*gel 36

首先,您的问题与 bash 无关,而与终端有关。终端正在响应显示程序的文本,一旦程序启动,bash 本身就无法控制程序。

终端提供控制序列来控制颜色、字体、光标位置等。有关标准化终端序列的列表,请查看 http://www.termsys.demon.co.uk/vtansi.htm您可以例如

  • 将光标定位在行首
  • 之后删除该行
  • 写一个新行

创建进度条。

更高级的终端转义序列通常依赖于终端,例如仅适用于 Eterm 或 xterm。ncurses - 是一个编程库,用于与终端创建交互式程序,因此您不必使用转义序列。

如何用终端序列覆盖现有行

echo long text
sleep 1
printf "\033[1A"  # move cursor one line up
printf "\033[K"   # delete till end of line
echo foo
Run Code Online (Sandbox Code Playgroud)

如何在没有终端序列的情况下覆盖现有行

一个简单的解决方案是不在末尾写换行符而是写回车,这基本上将光标重置到行首,例如:

echo -n first 
sleep 1 
echo -ne "\rsecond"
echo
Run Code Online (Sandbox Code Playgroud)

\r或回车就会把光标移动到该行的开头,并允许您覆盖该行的内容。

在缓冲区之间切换,如lessvi

的行为less也是由于更高级的终端功能,备用屏幕:

在 VT102 模式下,有转义序列来激活和停用备用屏幕缓冲区,其大小与窗口的显示区域相同。激活后,当前屏幕将被保存并替换为备用屏幕。在恢复正常屏幕之前,会禁用从窗口顶部滚动的行的保存。期限?xterm 的 cap(5) 条目允许可视化编辑器 vi(1) 切换到备用屏幕进行编辑并在退出时恢复屏幕。弹出菜单条目可以轻松地在普通屏幕和备用屏幕之间切换以进行剪切和粘贴。

http://rosettacode.org/wiki/Terminal_control/Preserve_screen列出了一些如何通过tput或一些转义序列自己完成的示例。


gle*_*man 15

不是使用echowhich 自动将换行符附加到字符串,而是使用printf "%s\r" whatever-- 回车将光标发送到当前行的开头。例子:

seq 1 15 | while read num; do printf "%2d\r" $num; sleep 1; done; echo ""
Run Code Online (Sandbox Code Playgroud)