实时修改 shell stdout

modifying shell stdout in real time

好吧,请耐心等待,因为我不是专业人士,这是一个概念验证项目,用于了解更多关于我的 shell、编程和基本 bash 脚本的信息。

所以我想做的是:每当我的终端打印出任何东西时,无论是命令的结果还是来自 shell 的错误消息,我都想应用一些 "filters"例如,如果我在终端中输入 "ls -a",我想获取命令 returns 的文件夹列表,但对字符应用 TIME DELAY,这样看起来该列表是实时输入的。

更具体地说,我希望脚本在 STDOUT 中获取每个字母数字字符,并花费特定时间(比如 100 毫秒)遍历随机字符(这些可以从列表中随机访问),然后最终停止在字符的原始值。

我所知道的: 不多,我是一般编程的新手,所以 bash 语言也是如此,但我可以阅读一些代码并浏览我发现这个 http://brettterpstra.com/2012/09/15/matrixish-a-bash-script-with-no-practical-application/ 脚本与 tput 一起玩。这向我展示了我想要实现的视觉效果是可以实现的……现在让它有序地、单独地发生在打印到 STDOUT 的每个字符上……这是我想不通的。

我的想法: 在我看来,我知道我可以将 STDOUT 传输到一个文件中,通过任何语言(比方说 python!)我可以进行各种字符串操作,然后 return 输出到 STDOUT但我希望实时操作字符,所以如果代码是

cool_chars="£ ア イ ウ エ オ カ キ ク ケ コ サ シ ス " 
stdout=whatever module works to grab STDOUT from shell as string
stdout = stdout.split(" ")
for word in stdout:
    for letter in word:
       n=0
       while (n<10):
            #print the following iteration in real time @ shell but how????
            print random.choice(cool_chars)
            #finally stop at correct character
            print letter
            n++

无论如何,我已经阅读了一些关于 curses 和 ncurses 的内容以及如何使用任何指定的参数创建新的 windows,我想知道这是否只是创建一个具有指定参数的终端的问题参数与 curses 库然后制作一个 link 以便每个新的终端实例打开我修改的 curses shell 或者如果我可以只做一个 bash shell 脚本或者如果它使用 python 之类的东西最简单。我知道以上所有都可以选择,但我正在寻找最简单但不一定是最节省资源的答案。

感谢任何帮助、评论、指点等。

这并没有完全回答你的问题,但它确实打印了任何输入,就好像它是实时输入的一样:

perl -MTime::HiRes -F -ane '$|=1;$old=""; foreach $char(@F){Time::HiRes::sleep(0.1); print "\r${old}${char}"; $old.=$char}' /etc/hosts

可以使用 STDIN 代替文件:

echo -e "abc\ndef\nghi" | perl -MTime::HiRes -F -ane '$|=1;$old=""; foreach $char(@F){Time::HiRes::sleep(0.1); print "\r${old}${char}"; $old.=$char}'

我们可以使用 shell 的睡眠来缩短它:

perl -F -ane '$|=1;$old=""; foreach $char(@F){`sleep 0.1`; print "\r${old}${char}"; $old.=$char}'

编辑:

下面的脚本应该可以完全解决您的问题:

#!/usr/bin/perl
use strict;
use utf8; 

binmode(STDOUT, ":utf8");

our $cols=`tput cols`;
our $|=1;
our $cursor="";

sub reset_line {
    print "\r" . " "x$cols . "\r";
}

sub pick_cursor {
    my @c = split (//,"£アイウエオカキクケコサシス");
    $cursor=$c[int(rand(1+@c))];
}


while (<>) {
    my $line="";
    my @a=split //;
    foreach my $char (@a) {
        `sleep 0.1`;
        reset_line;
        pick_cursor;
        if ( $char eq "\n" || $char =~ /\s/) {
            print "${line}${char}";
        }else {
            print "${line}${char}${cursor}";
        }
        $line .= $char;     
    }
}