10

我正在编写一个过滤器(在一个用于终端输出的管道中),有时需要“覆盖”刚刚发生的一行。它的工作原理是逐个字符地将标准输入传递给标准输出,直到\n达到 a,然后调用特殊行为。我的问题是如何返回到行首。

我首先想到的是使用 a\r或 ANSI 序列\033[1G。但是,如果行长到足以在终端上换行(并因此导致它滚动),这些只会将光标移回当前物理行。

我的第二个想法是跟踪行的长度(自上一个以来传递的字符数\n),然后\b多次回显。但是,如果该行包含控制字符或转义序列(可能还有 Unicode?),就会出错。

缺少搜索所有特殊序列并使用它来调整我的字符数,有没有一种简单的方法来实现这一点?

4

3 回答 3

3

即使有一个“魔术序列”在写入控制台时会可靠地擦除最后写入的行,您仍然会在输出中获得该行和序列(尽管隐藏在控制台上)。想想如果有人将输出写入文件,或者将其通过管道传递给其他过滤器会发生什么?他们会知道如何处理这样的输入吗?并且不要告诉我您排除了在其他地方写入而不是直接写入控制台的可能性。迟早会有人想要重定向输出 - 甚至可能是你!

做到这一点的正确方法是在处理每一行时将其缓冲在内存中,然后决定是否输出。真的没有办法解决这个问题。

于 2009-06-30T18:35:24.663 回答
2
$ cat >test.sh <<'EOF'
> #!/bin/sh
> 输入 sc
> echo '这是一个非常长的多行字符串:.................................. ..................................................... ......'
> tput rc
> echo '我回去重写了一些东西!!!!'
> 回声
> EOF
$ sh test.sh
我回去重写了一些东西!!!!……………………………………………………………………………………………………………………………………
..................................................... ……

在数据库中查找save_cursorrestore_cursor字符串功能。terminfo

于 2009-06-26T19:08:20.507 回答
0

您可以使用简单的方法查询终端尺寸ioctl

#include <sys/types.h>
#include <sys/ioctl.h>

// ...

struct winsize ws;
ioctl(1, TIOCGWINSZ, &ws);

// ws.ws_col, ws.ws_row should now contain terminal dimensions

这样,您可以防止打印超出行尾的任何内容,只需使用该\r方法即可。

于 2009-06-26T18:10:04.680 回答