如何在Perl中读取和写入管道?

kay*_*ahr 16 perl pipe

我是Perl noob,请原谅这个基本问题.我需要修改现有的Perl程序.我想通过外部程序管道一个字符串(可以包含多行)并读取该程序的输出.所以这个外部程序用于修改字符串.我们只是cat用作过滤程序.我试过这样但它不起作用.(输出cat到stdout而不是被读取perl.)

#!/usr/bin/perl

open(MESSAGE, "| cat |") or die("cat failed\n");
print MESSAGE "Line 1\nLine 2\n";
my $message = "";
while (<MESSAGE>)
{
    $message .= $_;
}
close(MESSAGE);
print "This is the message: $message\n";
Run Code Online (Sandbox Code Playgroud)

我已经读过Perl不支持它,因为它可能会陷入僵局,我可以理解它.但是我该怎么做呢?

tux*_*day 25

您可以使用IPC :: Open3实现与孩子的双向通信.

use strict;
use IPC::Open3;

my $pid = open3(\*CHLD_IN, \*CHLD_OUT, \*CHLD_ERR, 'cat')
    or die "open3() failed $!";

my $r;

for(my $i=1;$i<10;$i++) {
    print CHLD_IN "$i\n";
    $r = <CHLD_OUT>;
    print "Got $r from child\n";
}
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,`open2`的前两个参数与`open3`的反面方式相反!例如,它是`open2(\*CHLD_OUT,\*CHLD_IN,'cat'). (4认同)

Gre*_*con 10

这涉及系统编程,因此它不仅仅是一个基本问题.如上所述,您的主程序不需要与外部程序进行全双工交互.数据流沿一个方向传播,即

string→外部程序→主程序

创建此管道非常简单.Perl的open有用模式在perlipc文档"安全管道打开"部分中有说明.

进程间通信的另一个有趣方法是让您的单个程序进行多进程并在您自己之间进行通信.该open函数将接受任一文件参数"-|""|-"执行一个非常有趣的事情:它会分叉连接到您打开的文件句柄的子项.孩子正在运行与父母相同的程序.例如,当在假定的UID或GID下运行时,这对于安全地打开文件很有用.如果你打开管道减去,你可以写到你打开的文件句柄,你的孩子会在他的STDIN.如果您从减号打开管道,您可以从您打开的文件句柄中读取您的孩子写给他的任何内容STDOUT.

这是一个open涉及管道的管道,它给返回值带来细微差别.在perlfunc文档的open解释.

如果在命令上打开一个管道-(即指定|--|使用一个或两个参数形式open),fork则完成隐式,因此open返回两次:在父进程中它返回子进程的pid,并在子进程中返回(已定义)0.使用defined($pid)//确定是否open成功.

要创建脚手架,我们在从右到左的顺序使用工作open,以fork在每一步一个新的进程.

  1. 您的主程序已在运行.
  2. 接下来,fork最终将成为外部程序的过程.
  3. 在步骤2的过程中
    1. 首先fork是字符串打印过程,以使其输出到达我们的STDIN.
    2. 然后exec外部程序执行其转换.
  4. 让字符串打印机完成它的工作,然后exit开始更上一层楼.
  5. 回到主程序中,读取转换后的结果.

所有这些设置,你所要做的就是在底部植入你的建议,Cobb先生.

#! /usr/bin/env perl

use 5.10.0;  # for defined-or and given/when
use strict;
use warnings;

my @transform = qw( tr [A-Za-z] [N-ZA-Mn-za-m] );  # rot13
my @inception = (
  "V xabj, Qnq. Lbh jrer qvfnccbvagrq gung V pbhyqa'g or lbh.",
  "V jnf qvfnccbvagrq gung lbh gevrq.",
);

sub snow_fortress { print map "$_\n", @inception }

sub hotel {
  given (open(STDIN, "-|") // die "$0: fork: $!") {  # / StackOverflow hiliter
    snow_fortress when 0;
    exec @transform or die "$0: exec: $!";
  }
}

given (open(my $fh, "-|") // die "$0: fork: $!") {
  hotel when 0;

  print while <$fh>;
  close $fh or warn "$0: close: $!";
}
Run Code Online (Sandbox Code Playgroud)

感谢有机会撰写这样一个有趣的节目!