Perl6:检查STDIN是否有数据
Perl6: check if STDIN has data
在我的 Perl 6 脚本中,我想对标准输入进行(最好是非阻塞的)检查以查看数据是否可用。如果是这样,那我想处理一下,否则我想做其他事情。
示例 (consumer.p6
):
#!/usr/bin/perl6
use v6.b;
use fatal;
sub MAIN() returns UInt:D {
while !$*IN.eof {
if some_fancy_check_for_STDIN() { #TODO: this needs to be done.
for $*IN.lines -> $line {
say "Process '$line'";
}
}
say "Do something Else.";
}
say "I'm done.";
return 0;
}
作为 STDIN 生成器,我编写了另一个 Perl6 脚本 (producer.p6
):
#!/usr/bin/perl6
use v6.b;
use fatal;
sub MAIN() returns UInt:D {
$*OUT.say("aaaa aaa");
sleep-until now+2;
$*OUT.say("nbbasdf");
sleep-until now+2;
$*OUT.say("xxxxx");
sleep-until now+2;
return 0;
}
如果 consumer.p6
按预期工作,它应该产生以下输出,如果通过 ./producer.p6 | ./consumer.p6
调用:
Process 'aaaa aaa'
Do something Else.
Process 'nbbasdf'
Do something Else.
Process 'xxxxx'
Do something Else.
I'm done.
但实际上,它会产生以下输出(如果 if
条件被注释掉):
Process 'aaaa aaa'
Process 'nbbasdf'
Process 'xxxxx'
Do something Else.
I'm done.
您使用的是旧版本的 Perl 6,因为 v6.b
是该语言正式发布之前的版本。
所以我下面的一些内容可能需要更新的版本才能工作。
还有你为什么使用 sleep-until now+2
而不是 sleep 2
?
一种方法是将 .lines
变成 Channel,然后您可以使用 .poll
.
#!/usr/bin/env perl6
use v6.c;
sub MAIN () {
# convert it into a Channel so we can poll it
my $lines = $*IN.Supply.lines.Channel;
my $running = True;
$lines.closed.then: {$running = False}
while $running {
with $lines.poll() -> $line {
say "Process '$line'";
}
say "Do something Else.";
sleep ½;
}
say "I'm done.";
}
请注意,上面的代码目前在 my $lines = …
行阻塞;所以在第一行出现之前它不会开始做某事。要解决这个问题,您可以执行以下操作
my $lines = supply {
# unblock the $*IN.Supply.lines call
whenever start $*IN.Supply {
whenever .lines { .emit }
}
}.Channel;
在我的 Perl 6 脚本中,我想对标准输入进行(最好是非阻塞的)检查以查看数据是否可用。如果是这样,那我想处理一下,否则我想做其他事情。
示例 (consumer.p6
):
#!/usr/bin/perl6
use v6.b;
use fatal;
sub MAIN() returns UInt:D {
while !$*IN.eof {
if some_fancy_check_for_STDIN() { #TODO: this needs to be done.
for $*IN.lines -> $line {
say "Process '$line'";
}
}
say "Do something Else.";
}
say "I'm done.";
return 0;
}
作为 STDIN 生成器,我编写了另一个 Perl6 脚本 (producer.p6
):
#!/usr/bin/perl6
use v6.b;
use fatal;
sub MAIN() returns UInt:D {
$*OUT.say("aaaa aaa");
sleep-until now+2;
$*OUT.say("nbbasdf");
sleep-until now+2;
$*OUT.say("xxxxx");
sleep-until now+2;
return 0;
}
如果 consumer.p6
按预期工作,它应该产生以下输出,如果通过 ./producer.p6 | ./consumer.p6
调用:
Process 'aaaa aaa'
Do something Else.
Process 'nbbasdf'
Do something Else.
Process 'xxxxx'
Do something Else.
I'm done.
但实际上,它会产生以下输出(如果 if
条件被注释掉):
Process 'aaaa aaa'
Process 'nbbasdf'
Process 'xxxxx'
Do something Else.
I'm done.
您使用的是旧版本的 Perl 6,因为 v6.b
是该语言正式发布之前的版本。
所以我下面的一些内容可能需要更新的版本才能工作。
还有你为什么使用 sleep-until now+2
而不是 sleep 2
?
一种方法是将 .lines
变成 Channel,然后您可以使用 .poll
.
#!/usr/bin/env perl6
use v6.c;
sub MAIN () {
# convert it into a Channel so we can poll it
my $lines = $*IN.Supply.lines.Channel;
my $running = True;
$lines.closed.then: {$running = False}
while $running {
with $lines.poll() -> $line {
say "Process '$line'";
}
say "Do something Else.";
sleep ½;
}
say "I'm done.";
}
请注意,上面的代码目前在 my $lines = …
行阻塞;所以在第一行出现之前它不会开始做某事。要解决这个问题,您可以执行以下操作
my $lines = supply {
# unblock the $*IN.Supply.lines call
whenever start $*IN.Supply {
whenever .lines { .emit }
}
}.Channel;