关于ipc:如何从Perl脚本中捕获系统命令的stdin和stdout?

关于ipc:如何从Perl脚本中捕获系统命令的stdin和stdout?

How can I capture the stdin and stdout of system command from a Perl script?

在Perl脚本的中间,有一个我要执行的系统命令。 我有一个字符串,其中包含需要输入到stdin中的数据(该命令仅接受来自stdin的输入),并且我需要捕获写入stdout的输出。 我已经研究了Perl中执行系统命令的各种方法,并且open函数似乎是我所需要的,除了看起来我只能捕获stdin或stdout,不能同时捕获两者。

此刻,看来我最好的解决方案是使用open,将stdout重定向到一个临时文件中,并在命令完成后从该文件中读取。 有更好的解决方案吗?


IPC :: Open2 / 3很好,但是我发现通常我真正需要的只是IPC :: Run3,它能够以最小的复杂性很好地处理简单的情况:

1
2
3
use IPC::Run3;    # Exports run3() by default

run3( \@cmd, \$in, \$out, \$err );

该文档将IPC :: Run3与其他替代方案进行了比较。即使您不决定使用它,也值得一读。


perlipc文档涵盖了许多方法,包括IPC :: Open2和IPC :: Open3。


在脚本顶部的某处添加以下行

1
use IPC::Open2;

这将包括必要的模块,默认情况下通常会在大多数Perl发行版中安装该模块。 (如果没有它,则可以使用CPAN进行安装。)然后,而不是打开,调用:

1
$pid = open2($cmd_out, $cmd_in, 'some cmd and args');

您可以通过将数据发送到$ cmd_in来将其发送到命令,然后通过从$ cmd_out中读取来读取命令的输出。

如果还希望能够读取命令的stderr流,则可以改用IPC :: Open3模块。


IPC :: Open3可能会做您想要的。它可以捕获STDERR和STDOUT。

http://metacpan.org/pod/IPC::Open3


我最近发现的一种非常简单的方法是IPC :: Filter模块。它使您可以非常直观地完成工作:

1
$output = filter $input, 'somecmd', '--with', 'various=args', '--etc';

请注意,如果将列表传递给命令,它将如何在不通过外壳的情况下调用命令。它还可以很好地处理常见实用程序的错误。 (如果失败,则使用STDERR中的文本作为错误消息,它为die;成功时,仅丢弃STDERR。)

当然,由于它无法进行任何流处理,因此不适合用于大量数据。同样,错误处理的粒度可能不足以满足您的需求。但这使许多简单的情况确实非常简单。


有一个特殊的perl命令

1
open2()

可以在以下位置找到更多信息:http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html


我想您想看看IPC :: Open2


如果您不想包含额外的程序包,则可以

1
2
3
4
5
6
7
open(TMP,">tmpfile");
print TMP  $tmpdata ;
open(RES,"$yourcommand|");
$res ="" ;
while(<RES>){
$res .= $_ ;
}

这与您的建议相反,但也应该起作用。


如果我只希望输出一行,或者想将结果分割到换行符以外的其他地方,我总是这样做:

1
2
3
4
5
6
7
my $result = qx( command args 2>&1 );  
my $rc=$?;  
# $rc >> 8 is the exit code of the called program.

if ($rc != 0 ) {  
    error();  
}

如果要处理多行响应,请以数组形式获取结果:

1
2
3
4
5
6
7
my @lines = qx( command args 2>&1 );  

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}

推荐阅读