在我的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;