1

我想写:

... | my_filter | myperlprogram

但我不知道怎么跑my_filter,直到我开始了myperlprogram

我可以在阅读之前以某种方式myperlprogram循环 STDIN吗?my_filter

我在想类似的事情:

pipe($a,$b);
if(not fork()) {
   close STDOUT; 
   open STDOUT, $b;
   exec "my_filter --with the correct --options";
} else {
   close STDIN
   open STDIN, $a
}
# continue reading STDIN now looped through `my_filter`
4

2 回答 2

5

从描述中根本不清楚为什么一个简单的

open STDIN, '-|', 'your_filter', '--option1', ...

不行。

于 2019-05-02T22:59:38.737 回答
1

我看到问题的方式是:STDIN通过使用脚本运行后从脚本内部运行的外部程序来过滤脚本(因此,不是使用管道)。使用IPC::Run

use warnings;
use strict;
use feature 'say';

use IPC::Run qw(start pump finish);

my $filtered_in;
FILTER_IN: {        
    my @cmd = qw(a_filter.pl);  # add filter's options/arguments
    my $h = start \@cmd, \my $in, \$filtered_in;
    while (<>) { 
        $in = $_; 
        pump $h while length $in;

        # Wait for filter's output -- IF WANT to process lines as received
        pump $h until $filtered_in =~ /\n\z/;
        chomp $filtered_in;                    # process/use filter's output
        $filtered_in .= '|';                   # as it's coming (if needed)
    }    
    finish $h or die "Cleanup returned: $?";
};    
say $filtered_in // 'no input';

这允许人们在发出过滤器的输出行时对其进行处理。如果不需要,但我们只想累积过滤器的输出以供以后使用,那么您不需要下面的代码# Wait for...


最简单的测试,a_filter.pl例如

use warnings;
use strict;
STDOUT->autoflush(1);

my $cnt = 0;    
while (<>) { print "line ", ++$cnt, ": ", $_ }

然后运行

echo "a\nfew\nlines" | script.pl

带输出

第 1 行:a|第 2 行:少数|第 3 行:行|

来自我们script.pl上面的玩具加工。

这也将通过文件过滤输入,

script.pl < input.txt
于 2019-05-03T07:05:02.870 回答