2008-09-16 137 views
3

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

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

回答

3

脚本顶部的某处,包括行

use IPC::Open2; 

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

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

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

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

+1

对于阅读此内容的任何人,您应该确保并且不要像本示例那样使用裸号文件句柄。看到这个文档:http://www.perlfoundation.org/perl5/index.cgi?bareword_uppercase_filehandles – 2008-09-17 03:14:05

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(); 
    } 
} 
+0

我看不到你的例子在哪里处理STDIN。 – 2010-11-08 18:52:41

3

perlipc documentation涵盖了许多方法,你可以做到这一点,包括IPC :: Open2和IPC :: Open3。

6

IPC :: Open2/3都很好,但我发现,通常都是我真正需要的是IPC::Run3,它以最简单的处理简单的情况非常好:

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

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

的文档比较IPC: :Run3到其他选择。即使您不决定使用它,也值得阅读。

0

如果你不希望包括额外的软件包,你可以做

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

这是你的建议,相反,还应该工作。

2

我最近发现的一个非常简单的方法是IPC::Filter模块。它可以让你做的工作非常直观:

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

注意它是如何,如果你传递一个列表,而无需通过shell去调用你的命令。它还为处理常见实用程序的错误做了合理的工作。 (在失败时,它使用来自STDERR的文本作为其错误消息;在成功时,STDERR仅被丢弃。)

当然,由于它不提供任何方式来执行任何操作,因此它不适合大量数据流处理;此外,错误处理可能不够精细,无法满足您的需求。但它使得很多简单的案例真的很简单真的