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'。
因为那里有睡眠,所以您不会忙于等待按键(例如,轮询速度与处理器旋转速度一样快)。
#!/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'。
因为那里有睡眠,所以您不会忙于等待按键(例如,轮询速度与处理器旋转速度一样快)。