Perl 非阻塞用户输入

Perl non-blocking user input

#!/usr/bin/perl -w

use Term::ReadKey;
ReadMode('cbreak');

while (1) {
    $char = ReadKey(-1);
    next unless defined $char;
    printf("Char: $char Decimal: %d\tHex: %x\n", ord($char), ord($char));
}
ReadMode('normal');

以上效果很好。但是我希望能够在某些可执行文件为 运行 时获得用户输入。所以我尝试了以下但它不起作用。也许 运行 一个可执行文件在尝试获取用户输入时出错了?如果是这样,我该怎么做?

我正在从 $myexe 获取输出,根据用户输入,我想从 $myexe

中过滤不同的东西
#!/usr/bin/perl -w

use Term::ReadKey;
my $myexe = 'bin/myexecutable';
open my $EXE,
    "$myexe distribute 2>&1 |"
    or die 'Cannot open EXE';

ReadMode('cbreak');
while (<$EXE>) {
    $char = ReadKey(-1);
    if (defined $char) {
        print ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> $char\n"; #i would press a key but nothin prints out
    }
    print "$_\n";
}
ReadMode('normal');

我对 运行 的 'busy-wait' 循环持谨慎态度,就像您在 Term::ReadKey 中遇到的那样。但我的建议是——如果你想同时做两件事——可能值得考虑做一些并行代码。

类似于:

#!/usr/bin/perl
use strict;
use warnings;
use threads;
use threads::shared;

use Term::ReadKey;


my $myexe = 'bin/myexecutable';

my $filter : shared;


sub worker {
    open my $EXE, "$myexe distribute 2>&1 |"
        or die 'Cannot open EXE';
    while ( my $line = <$EXE> ) {

        #do something with filter here;
        print "$filter : $line";
    }

}

$filter = 0;
threads->create( \&worker );

my $keypress;
ReadMode 4;

while ( threads->list(threads::running) ) {
    while ( not defined( $keypress = ReadKey(-1) )
        and threads->list(threads::running) )
    {
        print "Waiting\nRunning:" . threads->list(threads::running) . "\n";
        sleep 1;
    }
    print "Got $keypress\n";
    $filter = $keypress;
}
ReadMode 0;

foreach my $thr ( threads->list ) {
    $thr->join();
}

这是一些相当简单的示例代码 - 您可以通过多种方式扩展它,但原理是这样的:

  • 您向 'do the work' 发起了一个话题。
  • 您在 'main' 线程中处理 'keypress watching'。

因为那里有睡眠,所以您不会忙于等待按键(例如,轮询速度与处理器旋转速度一样快)。