每当我clear
在终端中运行时,它都会从屏幕可见部分的顶部到当前行删除回滚缓冲区。我在多个终端仿真器中尝试过,但问题仍然存在。有什么方法可以改变的行为,使其clear
不触及回滚缓冲区?
我的终端之前的clear
命令:
clear
命令执行后回滚缓冲区
答案1
分析
您称这种行为“奇怪”,但这是设计使然。clear
它不会将文本移出屏幕,而是清除屏幕上显示的内容。严格来说,它只是告诉终端(终端仿真器)执行此操作。
在某些终端中,clear
可以有效地清除整个回滚缓冲区。至少clear
在我的 Kubuntu 中可以这样做;-x
我可以要求它不要这样做。请参阅man 1 clear
。
我的$TERM
是xterm-256color
,这clear
对我来说是有效的:
$ clear | od -c
0000000 033 [ H 033 [ 2 J 033 [ 3 J
0000013
$ clear -x | od -c
0000000 033 [ H 033 [ 2 J
0000007
clear -x
相当于printf '\033[H\033[2J'
,
soleclear
相当于printf '\033[H\033[2J\033[3J'
。
这些序列ANSI 转义代码.终端应该解释它们。
缩写 | 姓名 | 影响 | |
---|---|---|---|
CSI n ; m H |
杯子 | 光标位置 | 将光标移动到行n 、列m 。[…] |
CSI n J |
ED | 显示中擦除 | 清除部分屏幕。[…] |
注意clear
打印的内容很大程度上取决于$TERM
。例如,如果我选择一个“随机”终端:
$ TERM=ztx clear | od -c
0000000 033 E
0000002
上面clear
没有使用 ED;而是使用了 CNL:
缩写 | 姓名 | 影响 | |
---|---|---|---|
CSI n E |
中央核能实验室 | 光标下一行 | 将光标向下移动到行首n (默认1 )。[…] |
这并没有清除我的终端的屏幕。或许在实际中确实如此ztx
;或者不,我不知道。无论如何clear
“认为”终端是ztx
,并且对于ztx
CNL 来说是最好的选择。
无论如何,我们都可以构建并使用等效printf
命令。 的重点clear
是它会检查$TERM
环境,然后查看 terminfo 数据库(请参阅man 5 terminfo
)以确定如何清除屏幕。 而printf
我们需要手动执行此操作。
clear
在某些情况下(即对于某些值$TERM
),的某些实现打印出您想要的序列并非不可能。
然后是终端(终端模拟器)。即使clear
打印\033[2J
,终端也可能反应做你想做的事。也许有一个选项让你选择。你可以编写一个以这种方式做出反应的终端仿真器。
我经常使用 tmux,它实现了自己的回滚缓冲区。在内部它$TERM
扩展为screen
;clear
并且clear -x
都等同于printf '\033[H\033[J'
。当由 tmux 解释时,此序列会执行您想要的操作。但在 tmux 之外(在我的情况下,使用 Konsole 提供的回滚缓冲区),相同的序列会重现您的问题。我推断 tmux 是一个按您想要的方式做出反应的终端仿真器。
我的观点是:clear
根据终端“认为”的是什么,打印不同的东西;然后终端解释这些东西,并可能以任何方式做出反应。例如,你的clear
似乎做了我clear -x
所做的:它没有清除整个回滚缓冲区,只清除可见部分。所以也许你的clear
没有打印\033[3J
;或者也许它确实打印了,但你的终端无论如何都没有完全清除缓冲区。
或许$TERM
你可以找到不同的值你的 clear
咨询你的terminfo 数据库将能够你的终端仿真器可以做你想做的事。即使你能做到这一点,我也不认为这是正确的事情。改变$TERM
可能会破坏其他事情。
解决方案 1:tmux
使用 tmux 及其回滚缓冲区。我的测试表明它的行为符合您的要求(至少在clear
显示$TERM
为 时screen
)。该工具是一个终端多路复用器,我经常使用它,因为它其他 特征我必须明确地跳出这个思路来写这个答案的某些部分。
这可能是您在终端中工作方式的重大变化。在我看来观点这是值得的。请注意,使用 tmux 的回滚缓冲区与使用终端仿真器的回滚缓冲区在许多方面都不同。
至少考虑尝试一下 tmux。
解决方案 2:自定义clear
为 shell 函数
看起来您不想清除任何东西;您想将文本移出屏幕并将提示放在顶部。因此,让我们这样做:
clear() (
if [ "$#" -ne 0 ]; then
command clear "$@"
exit
fi
h="$(tput lines 2>/dev/null)"
if [ "$?" -eq 0 ]; then
until [ "$h" -le 1 ]; do
printf '\n'
h=$((h-1))
done
fi
command clear -x
)
函数clear
在不带参数调用时会覆盖命令;否则,它会返回命令。当它覆盖时,函数会打印正确数量的换行符,以将先前的内容移出屏幕;然后clear -x
调用常规来清除换行符并将提示符放在顶部。
笔记:
tput lines
不可移植。如果此命令存在任何问题,则该函数将仅调用command clear -x
。command clear -x
假设您的clear
可执行文件支持-x
与我的一样。从您不需要的问题来看-x
,您的唯一方法clear
不会清除整个缓冲区(可能是因为您的clear
不同;可能是因为您的终端不同)。printf '\033[H\033[2J'
改为调用可能就足够了。另一方面,command clear …
查阅 terminfo 数据库,这也是您可能希望从该函数中获得的功能。根据您的需要调整该函数。- 如果在函数运行时调整终端仿真器的大小,则函数可能会出现错误。如果需要调整大小,请在调用之前或之后进行
clear
,而不是在调用期间。 - 该函数可以在 tmux 内部使用。它在那里绝对不需要(因为 tmux 本身就是一个解决方案),但据我所知,它不会破坏任何东西。因此,例如,
~/.bashrc
如果您在 tmux 之外使用 Bash,则可以将该函数放在您的程序中,当您在 tmux 内部使用 Bash 时,一切仍然应该正常工作。 - 任何 shell 函数都是在 shell 中定义的。我们的代码可以转换为脚本(包装器),
clear
无论使用哪种 shell,都可以覆盖该脚本。
答案2
从手册页来看,clear -x
不会清除回滚缓冲区。
答案3
简短、便携的答案:
tput indn $LINES
... 将使当前终端“向上”滚动其所含的行数。
效果是“清除”屏幕,而不会丢失任何滚动缓冲区内容。
如其他地方所示:
tput indn $LINES | od -t x1z
...将显示正在发生的事情。(十六进制,此处附有字符解释)。
man terminfo
获得更多选项。
完全可以放入别名甚至是 bash 函数。
函数 scroll_up { 输入 indn $LINES }
注意:(shopt -s checkwinsize
更多信息;man bash)应该在您的$HOME/.bashrc
或$HOME/.bash_aliases
- 就像scroll_up
上面的功能一样。
还有一个注意事项:为了扩展可移植性,请确保shopt ...
使用
LINES=$(tput lines)