clear做了啥?
clear
做的工作很简单:把待输入的下一行移动到左上角。
所以你看,它根本没有真正对终端的内容进行清除,只不过是将其藏起来了。
如何实现clear
Linux的终端控制序列
Linux控制台实现了VT102和ECMA-48/ISO 6429/ANSI X3.64终端控制的子集,详见:console_codes - ubuntu man page。
Linux使用ANSI escape code方式来描述其控制序列,详见:ANSI escape code - Wikipedia。
简而言之,使用ESC
符号开始的一串字符序列会被解析成控制序列,多数控制序列由CSI(control sequence introducer)开始,由ESC [
来表示。
使用printf命令实现clear
printf
支持终端控制序列,其中ESC
可以用\e
转义符表示。
console_codes - ubuntu man page中给出了一个表(节选):
Sequences | Name | Describe |
---|---|---|
ESC @ | ICH | Insert the indicated # of blank characters. |
ESC A | CUU | Move cursor up the indicated # of rows. |
ESC B | CUD | Move cursor down the indicated # of rows. |
ESC C | CUF | Move cursor right the indicated # of columns. |
ESC D | CUB | Move cursor left the indicated # of columns. |
ESC E | CNL | Move cursor down the indicated # of rows, to column 1. |
ESC F | CPL | Move cursor up the indicated # of rows, to column 1. |
ESC G | CHA | Move cursor to indicated column in current row. |
ESC H | CUP | Move cursor to the indicated row, column (origin at 1,1). |
ESC J | ED | Erase display (default: from cursor to end of display). |
ESC [ 1 J | erase from start to cursor. | |
ESC [ 2 J | erase whole display. |
维基百科中ANSI escape code - Wikipedia中也说到:
CSI 2 J — This clears the screen and, on some devices, locates the cursor to the y,x position 1,1 (upper left corner).
CSI 2 J
或ESC [ 2 J
指令会在清除屏幕后将光标移动到第一行第一列(左上角)。
结合printf
,得出以下命令:
printf "\e[2J"
不知道是不是Linux水土的问题,这个命令执行效果和描述不太一样,其实际效果是将当前行顶出屏幕外(负一行),并打印若干空白行(尼玛)。
为了修正这个问题,我们看到有个指令ESC H
,描述如下:
Move cursor to the indicated row, column (origin at 1,1).
于是我们可以借助这个指令来完善我们的功能,修改如下:
printf "\e[H\e[2J"
这下终于完成我们坑爹的clear
命令。
难道就只是这样吗?
clear
命令这么坑爹Linus Torvalds知道吗?
实现一个真正意义上的clear
在console_codes - ubuntu man page中发现了另一个东西:
Sequences | Name | Describe |
---|---|---|
ESC c | RIS | Reset |
重置你的终端来达到清除内容的效果。
printf "\ec"
真是一个简单又暴力的方法。
推荐写成shell脚本并移动到/usr/bin/目录下。