为什么`clear`不清除整个屏幕?

Eug*_*kov 4 terminal gnome-terminal

当我使用clear命令清除屏幕时。它没有被清除(当我在命令完成后向上滚动一点时查看屏幕截图)

在此处输入图片说明

所以我将命令加倍以获得正确的行为:

$ clear && clear && DD=0 ...
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

为什么我需要将命令加倍才能清除屏幕?

UPD

实际上,如果我只是clear清除了屏幕。但我可以向上滚动并查看最后 25 行(如果屏幕为 80x25)。当我跑步时,clear;clear我清除了这些线条。

Jde*_*eBP 11

这里要注意的重要一点是问题上的标签。此行为特定于 GNOME 终端和任何其他基于 libvte 构建的终端模拟器。您不会在 Xterm、Unicode RXVT、Linux 内核内置的终端模拟器或 FreeBSD 控制台中看到这一点。

一般发生的事情是这样的。

  1. clear命令查看 terminfo/termcap 并发出适当的控制序列。
    1. 如果 terminfo/termcap 条目具有E3它的能力,它首先将其写出。这会发出控制序列以清除回滚缓冲区。这和背后还有中详细记录了历史的迪基的ncurses手册页的clear命令
    2. 然后它使用clear清除可见屏幕的功能。
  2. terminfo/termcap 条目中的控制序列由终端类型决定;但是,除了使用 FormFeed 清除屏幕的(现在很少见的)终端(DEC VT 及其模仿者不这样做)之外,它们要么只是普通的旧 ECMA-48 控制序列或对其的扩展。举些例子:
  3. 终端仿真器作用于控制序列。根据 ECMA-48 及其 Xterm 扩展的定义:
    • CSI H(CUP) 放置光标。
    • CSI 0 J(ED 0) 或仅 CSIJ从当前光标位置擦除到屏幕末尾。
    • CSI 2 J(ED 2) 擦除整个屏幕。
    • CSI 3 J(ED 3) 擦除回滚缓冲区。

特别是在 GNOME 终端方面:

  1. 终端类型是正确的gnome,但有些人错误地将其设置为xterm.
  2. gnometerminfo项没有定义的E3能力,并在许多系统-依旧!-xterm条目也没有,因为它没有从Dickey terminfo渗透下来。所以clear只写出clear能力的内容。
  3. clear这些 terminfo 条目的功能内容是将光标归位然后擦除整个屏幕的控制序列。
  4. 但是 GNOME 终端没有正确实现擦除整个屏幕。 更具体地说,它所基于的库 libvte 在VteTerminalPrivate::seq_clear_screen()函数代码中没有这样做。相反,libvte 将屏幕向下滚动整个屏幕的空白行,并将光标位置移动到这些空白行中的第一个。

这就是为什么你会看到你所看到的。当被告知时,libvte 不会擦除整个屏幕。相反,它正在做一些与此表面相似的事情,直到人们完全按照提问者在这里所做的事情进行:将终端窗口向后滚动以查看回滚缓冲区。那么差别就很明显了。

在 Xterm 和 Unicode RXVT 等其他终端仿真器上,ED 2 控制序列确实会擦除屏幕,从上到下擦除屏幕上的每个位置,并且不会改变回滚缓冲区。但是在 libvte 终端模拟器上,它只是将当前屏幕推入回滚缓冲区并添加一个屏幕的空白行。先前的屏幕内容不会被擦除,而是被转移到回滚缓冲区中。

如果您运行该clear命令两次,它会添加两个屏幕的空白行。如果您的回滚缓冲区足够大,您仍然可以找到原始屏幕内容,只需在回滚缓冲区中进一步向上即可。

进一步阅读

  • 也许做`alias clear='clear && printf "\033[3J"'` 是一个可行的解决方案? (2认同)
  • “但是 GNOME 终端没有正确地实现擦除整个屏幕。” – 这确实是 VTE 与 xterm 不同的地方之一,您甚至链接了它的跟踪错误。请注意,xterm 的行为也有 VTE 没有的缺点,例如,在 bash 中按 Ctrl+L 会清除 xterm 中的最后一屏数据,但不会清除 gnome-terminal 中的数据。 (2认同)