在我的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-Generator,我编写了另一个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是在该语言正式发布之前.
因此,我在下面的一些内容可能需要更新的版本才能工作.
因此,我在下面的一些内容可能需要更新的版本才能工作.
另外你为什么要睡觉 – 直到现在2而不是睡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;