在 Linux 终端中如何向上移动一行?

3

我知道可以使用\r回到上一行并覆盖其内容。
现在如何进入前一行以更改内容?
或者是否有一种方法可以将内容打印到控制台窗口的特定光标位置?

我的目标是使用PHP创建一些自刷新的多行控制台应用程序。

5个回答

11

使用ANSI转义码移动光标。例如:Esc [ 1 F。要将Escape字符放入字符串中,您需要以数值方式指定其值,例如"\x1B[1F"

sujoy建议,您可以使用PHP ncurses以更抽象的方式移动光标。

虽然大多数“控制台”都支持ANSI转义码,但其他类型的终端使用不同的字符序列,ncurses提供了一个标准化的API,它是终端独立的。如果您感兴趣,可以快速查看/etc/termcap(然后查看man terminfo)。

更新:Lars Wirzenius的回答有一个有用的背景概述。几年前,我还写了一篇关于终端的简短文章。


7
Linux虚拟控制台模拟了旧式显示终端,但并非完美。请参见VT-100硬件的Wikipedia页面以了解示例。
这些终端从串行端口读取数据,并在屏幕上显示它们。它们还会在输入流中查找特殊字节,并以其他方式对其进行处理。例如,换行符('\n',字节值为10)将移动到下一行的开头,而回车符('\r',字节值为13)将移动到当前行的开头。
更有趣的是,ASCII ESC字节(27)将启动一个命令序列,可以对光标或显示执行几乎任何操作。其中一个序列可能会将光标移动到屏幕左上角,另一个序列则可能移动到给定的行和列。第三个序列可能会清除屏幕,第四个序列可能会使文本以反向颜色显示。
每个终端制造商都会发明自己的命令序列(它们也不总是以ESC开头),然后根据他们可以让新版本的硬件做什么来更改它们。如果制造商添加了颜色或简单的图形,则会产生新的序列。
适应每个终端和每个命令序列的每个应用程序都是一项艰巨的任务。将其与适应每个Web应用程序到新的浏览器版本进行比较。
通常的解决方案是添加一个抽象层。在Unix中,最初的抽象称为“termcap”,包括文件“/etc/termcap”和一个读取该文件的库。该文件将指定每个终端型号的每个逻辑操作发送的实际命令序列。因此,“vt102”终端模型将将操作“清除屏幕”映射到“\033[2J”。这使应用程序员可以以逻辑操作为基础思考,这要简单得多。
当然,并不够简单... termcap库并不像它本来可以那样好,因此开发了另外两个库:curses提供更高的抽象级别,包括用户输入,而terminfo则使终端定义及其被程序员使用更加容易。
现代,ncursescurses 的一个免费重新实现,terminfo 已经基本完全取代了 termcap。此外,ANSI 定义了一些“标准”序列,基于数字终端,并且几乎每个终端仿真器都使用这些序列,至少大多数是这样的,Linux 虚拟控制台就是其中之一。现在很少有人使用实际物理终端。
对于您想要做的事情,ncursestput 命令可能最有用。或者您可以决定只清除整个屏幕(参见 clear(1)),然后输出内容最简单。

1
对“ANSI”转义序列的背景做出良好总结加1分。(尽管我仍然使用使用termcap术语的应用程序,并且我还在某个盒子里保存了一个串行VT520) - RedGrittyBrick
我认为现代(21世纪)的Linux系统中,ncurses或terminfo现在提供了一个termcap兼容性功能,但我可能错了。 - user25148

1
我的目标是使用PHP创建一些自刷新的多行控制台应用程序。
为了实现你想要的功能,ncurses 是最好的选择。

我考虑过这个问题,但是 PHP 没有附带 ncurses 包装器 :-( - Cobra_Fast
@Cobra_Fast:我个人没有使用过ncurses和php,但是之前有使用过ncurses,应该也有适用于php的库 :) - Sujoy

1
你应该了解一下ncurses。在shell中,你可以通过以下方式向上移动一行:
tput cuu1

查看 man terminfo 以获取更多选项。 但执行 shell 命令来移动光标是相当令人绝望的。


-2

你可以使用键盘上的上下箭头来滚动控制台历史记录,但也有一个 history 命令。使用 man history 了解更多信息。


是的,我不是在寻找浏览历史记录的方法。我正在尝试更改脚本中先前输出的行。 - Cobra_Fast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接