前几天社团招新摆摊,打算用 Node.js 做个基于命令行的简单的抽题程序(大一上C语言课作业水平)

期间遇到个问题,作为一个活动用的抽题程序,抽完的题目不能留在界面上,否则就相当于透答案了,所以需要有个清空屏幕的指令。在 Windows 系统,清空指令可以简单地通过执行 cmd 自带的 cls 命令来完成(C 语言用 system("cls");)。但在 Linux 并没有 cls,与之对应的是 clear 命令,所以我直接用类似 system("clear"); 这样的语句就好了?

准备采取这个方案之前,无意中楼主开始好奇一个问题:Linux 的 clear 命令是怎么实现的呢?

用 Linux 的时间长了,大概有这样的一个印象:终端只是一个壳而已,命令是通过 shell 来处理的,我用 bash 可以 clear,用 zsh 也能 clear。运行 whereis clear 命令,也可以发现这个命令实际上是路径为 /usr/bin/clear 的可执行文件。所以是 clear 程序和终端之间有什么通信的方式?

突发奇想,运行 clear > out.txt 把命令的输出重定向到了 out.txt 上,然后打开这个文件,发现了一些神奇的字符。

直接把这个文件输出,竟和直接运行 clear 一样的效果!

看来程序是通过输出一些神奇的特殊字符来实现与控制终端的。

开始一番搜索,其中发现了一台型号为 VT100 的就叫终端的机器。VT100 - Wikipedia

原来这就是最原始的 stdio 啊哈哈哈

另外还有刚刚遇到的一系列神奇字符的说明表:
ANSI/VT100 Terminal Control

试着在终端里面运行 echo "\033c",同样也实现了清屏功能。直接运行 cat,按 Esc 键(也就是\033所转义的)和 c ,回车,发现也清屏了。

所以这和我们平常使用的终端软件有什么区别呢,带着这个问题,翻到了 Ubuntu 自带的 gnome-terminal 的帮助文档。

心中也有了一个大概的印象,所以,那个抽题的程序,就不用研究怎么在 Node.js 平台像 C 语言的 system 函数一样运行外部命令了,直接 console.log("\033c"); 就完事儿。

不禁感慨,虽说终端机早已停产,但是通过终端模拟器软件, CLI 仍然在这个世界上继续发挥着独特但又至关重要的作用。

13 天 后

我运行 cat 后,输入 ctrl+[ 和 c ,或者输入 alt+c 后回车,也能达到清屏的效果,它们产生的字符是相同的。感觉这几个键背后还有故事~
一种说法是 ctrl+ 字符会自动产生字符相应 ascii - 64 的码,而 [ (101 1011) 的 ascii - 64 恰好就是 esc (001 1011)

    hsxfjames
    也特别好奇 ^[ 里面的 ^ 是代表着什么含义,^[ 本身应该也是一个单个的字符

      0x0001
      刚搜了下, ^@ 是一种简记法, ^ (caret) 就代表着 ctrl
      Control characters
      Caret notation
      How to write or abbreviate Ctrl or control

      也就是说 ctrl+@ ( @ 可为 ascii 中任一字符)是一个可以产生控制字符的组合键,每一个 ^@ 都是一个不可打印的控制字符。不过 alt+c 的用法我还没找到, caret notation 也没见到比较好的中文翻译。上标号记法?插入号记法?....

      更多:Linux console escape and control sequences


      ps 话说你这个 md 编辑器好像不支持 html ,也没有太多扩展语法,只能用加粗代替下划线(逃

        我也想说点:
        我在使用 Windows 和 Linux 的时侯留意到了一些细小的区别,比如
        *nix系终端的清屏,如本帖主题所言,是通过输出控制字符来实现的。实际使用的时候就会发现在执行clear后,如果鼠标滚轮往上滑一下,仍然可以看到之前的内容。
        而巨硬家的终端(command.com cmd.exe pwsh.exe),在执行cls后则不能看到之前的内容。我的猜测是在输出控制字符(或者根本没输出)后直接清空了终端的缓存。

          0xdeadbeef
          我运行 clear 跟楼主一样是产生 ^[[3J^[[H^[[2J 的,而真正的清除是 ^[c
          如果运行 printf "\033c" 你会发现历史记录都没了,滑不上去了,是真的全清掉了

          至于为什么 clear 没有产生真正的清除,我猜是环境or兼容性问题.. clear 的包是 ncurses-bin ,通过 apt source ncurses-bin 就可以把它的源码下载下来, clear 的实现在 progs/clear.c 里面,可以看到它是有尝试清除滚动缓存区(Clear the scrollback buffer if possible)的,最终不知道为什么失败了orz....


          upd: 我有个奇怪的发现,在 ubuntu 18.04 上运行 clear (ncurses 6.1.20180127) 的话,连续跑两次,之后往上滚就只能看到上一次 clear 的记录了.. 但如果加上 -x 选项的话还是能看到 clear 之前的操作记录

          8 个月 后
          1 年 后

          从这里发现了一个在 mac 下 iterm2 也能用的 https://gitlab.com/gnachman/iterm2/-/issues/6441

          alias cls='printf "\033[2J\033[3J\033[1;1H"'

          © 2018-2025 0xFFFF