如何使“clear”保留整个回滚缓冲区?

Man*_*noj 2 linux terminal command-line

每当我在终端中运行时clear,它都会删除从屏幕可见部分顶部到当前行的回滚缓冲区。我已经在多个终端模拟器中尝试过,问题仍然存在。有什么方法可以改变它的行为,clear使其不触及回滚缓冲区?

命令之前我的终端clear

“清除”命令之前的终端

clear命令后回滚缓冲区

“清除”命令后回滚缓冲区

Kam*_*ski 8

分析

\n

您称这种行为“奇怪”,但这是设计使然。clear不会将文本移出屏幕,它实际上会清除屏幕上的内容。严格来说,它只是告诉终端(终端仿真器)执行此操作。

\n

在某些终端中,clear有效地清除整个回滚缓冲区。至少clear在我的 Kubuntu 中是这样的;我可以要求-x它不要这样做。看man 1 clear

\n

我的$TERMxterm-256color,这clear对我来说是这样的:

\n
$ clear | od -c\n0000000 033   [   H 033   [   2   J 033   [   3   J\n0000013\n$ clear -x | od -c\n0000000 033   [   H 033   [   2   J\n0000007\n
Run Code Online (Sandbox Code Playgroud)\n

clear -x相当于printf \'\\033[H\\033[2J\',
\nsoleclear相当于printf \'\\033[H\\033[2J\\033[3J\'.

\n

这些序列是ANSI 转义码。终端应该解释它们。

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
缩写姓名影响
CSI n ; m H杯子光标位置将光标移动到行n、列m。[\xe2\x80\xa6]
CSI n J急诊科擦除显示清除部分屏幕。[\xe2\x80\xa6]
\n
\n

请注意clear打印的内容很大程度上取决于$TERM. 例如,如果我选择一个“随机”终端:

\n
$ TERM=ztx clear | od -c\n0000000 033   E\n0000002\n
Run Code Online (Sandbox Code Playgroud)\n

以上clear没有使用ED;它使用 CNL:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
缩写姓名影响
CSI n E中国国家实验室光标下一行将光标移动到行首n(默认1)。[\xe2\x80\xa6]
\n
\n

这不会清除我终端中的屏幕。也许在现实中确实如此ztx;或者没有,我不知道。无论如何,clear“认为”终端是ztx并且对于ztxCNL 来说是最好的选择。

\n

无论如何,我们可以构建并使用等效的printf命令。其要点clear是它检查$TERM环境,然后查看 terminfo 数据库(请参阅 参考资料man 5 terminfo)以确定如何清除屏幕。我们需要printf手动执行此操作。

\n

clear在某些情况下(即对于某些值) ,某些实现可能会$TERM打印出执行您想要的操作的序列。

\n

然后是终端(终端模拟器)。即使clear打印\\033[2J,终端也可能会按照您想要的方式做出反应。也许有一个选项可以让您选择。您可以编写一个以这种方式做出反应的终端模拟器。

\n

我经常使用 tmux,它实现了自己的回滚缓冲区。它的内部$TERM扩展为screenclearclear -x都等价于printf \'\\033[H\\033[J\'. 当 tmux 解释时,该序列会执行您想要的操作。但在 tmux 之外(在我的例子中,使用 Konsole 提供的回滚缓冲区)相同的序列会复制您的问题。我推断 tmux 是一个终端模拟器,可以按照您想要的方式做出反应。

\n

我的观点是:clear打印不同的东西,取决于它“认为”你的终端是什么;然后终端解释这些东西,它可能会以任何方式做出反应。例如,您clear似乎做了我clear -x所做的事情:它不会清除整个回滚缓冲区,仅清除可见部分。所以也许你的clear不打印\\033[3J;或者也许确实如此,但您的终端无论如何都没有完全清除缓冲区。

\n

也许您可以找到不同的值,$TERM这样 clear查询terminfo 数据库就能够使您的终端仿真器执行您想要的操作。即使你能做到这一点,我也不会说这总体上是正确的事情。改变可能会破坏其他事情。$TERM

\n
\n

解决方案1:tmux

\n

使用 tmux 及其回滚缓冲区。我的测试表明它的行为符合您想要的方式(至少当clear看到$TERMas时screen)。该工具是一个终端多路复用器,由于它的其他 功能,我经常使用它,并且我必须明确地摆脱它来编写这个答案的某些部分。

\n

这可能是您在终端中工作方式的重大变化。在我看来这是值得的。请注意,使用 tmux 的回滚缓冲区在许多方面与使用终端仿真器的回滚缓冲区不同。

\n

至少考虑尝试 tmux。

\n
\n

方案二:自定义clear为shell函数

\n

看来你不想清除任何东西;您想要将文本移出屏幕并将提示放在顶部。那么让我们这样做:

\n
$ clear | od -c\n0000000 033   [   H 033   [   2   J 033   [   3   J\n0000013\n$ clear -x | od -c\n0000000 033   [   H 033   [   2   J\n0000007\n
Run Code Online (Sandbox Code Playgroud)\n

clear当不带参数调用时,该函数会覆盖命令;否则它会回退到命令。当它重写时,该函数会打印正确数量的换行符,以将先前的内容移出屏幕;然后clear -x调用常规来清除换行符并将提示符放在顶部。

\n

笔记:

\n
    \n
  • tput lines不便于携带。如果此命令有任何问题,则该函数将仅调用command clear -x.
  • \n
  • command clear -x假设你的clear可执行文件-x像我的一样支持。从您不需要的问题来看-x,您的鞋底clear没有清除整个缓冲区(也许因为您的clear不同;也许因为您的终端不同)。打电话可能就足够了printf \'\\033[H\\033[2J\'。另一方面,command clear \xe2\x80\xa6查阅 terminfo 数据库,这也是人们可能想要从该功能中获得的功能。根据您的需要调整功能。
  • \n
  • 如果在函数运行时调整终端仿真器的大小,则函数可能会出现错误。如果需要调整大小,请在调用之前或之后进行clear,而不是在调用期间进行。
  • \n
  • 该函数可以在 tmux 内部使用。那里绝对不需要它(因为 tmux 本身就是一个解决方案),但据我所知它不会破坏任何东西。例如,您可以将该函数放在您的~/.bashrc如果您在 tmux 之外使用 Bash,则可以将该函数放在您的中,并且当您在 tmux 内使用 Bash 时,仍然可以正常工作。
  • \n
  • 任何 shell 函数都是在 shell 中定义的。我们的代码可以转换为覆盖的脚本(包装器)clear无论外壳如何,都可以覆盖。
  • \n
\n