【问题标题】:modifying shell stdout in real time实时修改shell标准输出
【发布时间】:2015-02-05 11:57:42
【问题描述】:

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

所以我想要做的是:每当在我的终端中打印出任何内容时,无论是命令的结果还是来自 shell 的错误消息,我都想对正在显示的内容应用一些“过滤器”,例如如果我在终端中输入“ls -a”,我想获取命令返回的文件夹列表,但对字符应用 TIME DELAY 以便看起来列表是实时输入的。

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

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

我的想法: 在我看来,我知道我可以将 STDOUT 用管道传输到一个文件中,通过任何语言(比如说 python!)我可以进行各种字符串操作,然后将输出返回到 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 以及如何使用任何指定参数创建新窗口的内容,我想知道是否只是使用 curses 库创建具有指定参数的终端和然后创建一个链接,以便每个新的终端实例打开我修改后的 curses shell,或者我是否可以只做一个 bash shell 脚本,或者使用 python 之类的东西最容易。我知道以上所有内容都可以作为选项,但我正在寻找最简单但不一定是资源效率最高的答案。

感谢任何帮助、cmets、指针等。

【问题讨论】:

  • 您必须连接到终端驱动程序或外壳程序才能拦截正常的标准输出。看看 screen 和/或最好是 tmux 如何通过伪 tty 拦截。
  • 感谢您接受我的回答,我使用脚本对其进行了编辑,完全解决了您的问题。
  • 也许你想要watchtail -f

标签: bash shell text scripting stdout


【解决方案1】:

这并不能完全回答您的问题,但它会打印任何输入,就好像它正在实时输入一样:

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 的 sleep 来缩短它:

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;     
    }
}

【讨论】:

  • 几乎!哈哈,我是 PERL 的新手,所以我需要花一点时间来弄清楚所有内容的含义($|=1 正在刷新缓冲区??? ...ok)所以这使得我首先编写的所有内容都变得可见这次在屏幕上看到它的第二次迭代以 0.1 延迟更改字符但它不解析参数(所以如果我输入“ls -a”它实际上不会将命令传递给终端)并且它似乎正在使用 STDIN 而不是 STDOUT。
  • 这是很棒的代码,因为我可以玩它,弄清楚一切意味着什么,我知道这几乎可以满足我的所有需求。谢谢蒂亚戈。我正在使用 GOOGLE 来赞美我的编码文盲,但是这里的 x 是什么意思 " print "\r" . " "x$cols . "\r"; " 你为什么使用 "our" (它到底是什么?) @c @a 呢?附言您对将命令解析到终端/将此代码应用于命令的 STDOUT 有何想法
  • 我的错,我通常用单线解决问题,所以我不擅长评论我的代码。如果您有任何疑问,请喊,但这是一个非常简单的脚本,我无法用一行解决它的唯一原因是因为花哨的光标:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-24
  • 2013-10-31
  • 2012-03-30
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多