4

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

目前,似乎我最好的解决方案是使用open,将标准输出重定向到一个临时文件,并在命令完成后从文件中读取。有更好的解决方案吗?

4

9 回答 9

6

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

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

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

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

于 2008-09-17T03:41:23.867 回答
3

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

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

于 2008-09-16T22:48:55.457 回答
3

在脚本顶部的某处,包括该行

use IPC::Open2;

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

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

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

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

于 2008-09-16T23:04:01.287 回答
3

perlipc 文档涵盖了您可以执行此操作的多种方法,包括 IPC::Open2 和 IPC::Open3。

于 2008-09-17T02:31:29.463 回答
2

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

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

请注意,如果您将列表传递给它,它会如何调用您的命令而无需通过 shell。它还可以合理地处理常见实用程序的错误。(失败时,它die使用来自 STDERR 的文本作为其错误消息;成功时,STDERR 将被丢弃。)

当然,它不适合处理大量数据,因为它无法进行任何流处理;此外,错误处理可能不足以满足您的需求。但它使许多简单的案例变得非常简单。

于 2008-09-17T11:36:36.623 回答
1

我想你想看看IPC::Open2

于 2008-09-16T22:49:23.537 回答
1

有一个特殊的 perl 命令

open2()

更多信息请访问:http ://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html

于 2008-09-16T22:54:19.233 回答
0

如果我只期望单行输出或想要将结果拆分为换行符以外的其他内容,我总是这样做:

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

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

如果要处理多行响应,请将结果作为数组获取:

my @lines = qx( command args 2>&1 );  

foreach ( my $line ) (@lines) {  
    if ( $line =~ /some pattern/ ) {  
        do_something();  
    }  
}  
于 2008-09-16T23:26:16.427 回答
0

如果你不想包含额外的包,你可以这样做

open(TMP,">tmpfile");
print TMP  $tmpdata ;
open(RES,"$yourcommand|");
$res = "" ;
while(<RES>){
$res .= $_ ;
}

这与您的建议相反,但也应该有效。

于 2008-09-17T08:53:45.767 回答