与编写新行相比,如何更改终端上行的内容?


24

因此,当wget获取网页时,它会显示一个状态栏,指示已下载文件的数量。看起来像这样:

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

但是,它不会像往stdout那样写另一行并添加另一个进度条,而是像下面这样更新它:

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

wget也不是唯一的例子。例如,当您通过管道将某些东西less然后退出时,原始提示以及先前运行的所有命令的结果仍然存在。就像你从未离开过。

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


5
我建议阅读BashFAQ 44。您可能会发现它很有趣。
2012年

Answers:


32

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

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

  • 将光标置于行首
  • 之后删除该行
  • 写新行

创建进度条。

更高级的终端转义序列通常取决于终端,例如仅与Eterm或xterm一起使用。诅咒是一个编程库,可以与终端创建交互式程序,因此您不必使用转义序列。

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

echo long text
sleep 1
printf "\033[1A"  # move cursor one line up
printf "\033[K"   # delete till end of line
echo foo

如何在不使用终端顺序的情况下覆盖现有线路

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

echo -n first 
sleep 1 
echo -ne "\rsecond"
echo

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

在缓冲区之间切换,例如lessvi

的行为less还归功于更高级的终端功能,即备用屏幕:

在VT102模式下,有一些转义序列可以激活和禁用备用屏幕缓冲区,该缓冲区的大小与窗口的显示区域相同。激活后,当前屏幕将保存并替换为备用屏幕。在恢复正常屏幕之前,将无法保存从窗口顶部滚动出来的行。xterm的termcap(5)条目允许可视编辑器vi(1)切换到备用屏幕进行编辑,并在退出时恢复该屏幕。弹出菜单条目使在剪切和粘贴的普通屏幕和备用屏幕之间切换变得简单。

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


15

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

seq 1 15 | while read num; do printf "%2d\r" $num; sleep 1; done; echo ""

根据终端的光标,可能会更令人高兴printf "\r%2d " $num
格伦·杰克曼
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.