有没有办法将数据从Perl传递到Unix命令行实用程序

时间:2010-12-07 21:55:07

标签: perl bash unix

我有一个来自第三方的命令行实用程序(它很大,用Java编写),我一直用它来帮助我处理一些数据。该实用程序需要行分隔文件中的信息,然后将处理后的数据输出到STDOUT。

在我的测试阶段,我写了一些Perl来创建一个充满要处理的信息然后将该文件发送到第三方实用程序的文件,但是因为我接近将这些代码投入生产,我'我真的更喜欢直接将数据传输到这个实用程序,而不是先将数据写入文件,因为这样可以节省必须将不需要的信息写入磁盘的开销。我最近在这个板上问过我如何在Unix中做到这一点,但后来才意识到直接从Perl模块中运行它会非常方便。也许是这样的事情:

system(bin/someapp do-action --option1 some_value --input $piped_in_data)

目前我按如下方式调用该实用程序:

bin/someapp do-action --option1 some_value --input some_file

基本上,我想要的是将所有数据写入变量或STDOUT,然后通过SAME Perl脚本或模块中的系统调用将其传输到Java应用程序。这将使我的代码更加流畅。如果没有它,我最终需要编写一个Perl脚本,该脚本调用一半的bash文件,反过来需要调用另一个Perl脚本来准备数据。如果可能的话,我很乐意在整个过程中留在Perl。有什么想法吗?

3 个答案:

答案 0 :(得分:8)

如果我正确地阅读你的问题,你想要产生一个进程,并且能够写入它的stdin并从它的stdout读取。如果是这种情况,那么IPC::Open2正是您所需要的。 (另请参阅IPC::Open3,您还需要阅读流程'stderr。)

以下是一些示例代码。我已经标记了你必须改变的区域。

#!/usr/bin/perl

use strict;
use warnings;

use IPC::Open2;

# Sample data -- ignore this.
my @words = qw(the quick brown fox jumped over the lazy dog);

# Automatically reap child processes.  This is important when forking.
$SIG{'CHLD'} = 'IGNORE';

# Spawn the external process here.  Change this to the process you need.
open2(*READER, *WRITER, "wc -c") or die "wc -c: $!";

# Fork into a child process.  The child process will write the data, while the
# parent process reads data back from the process.  We need to fork in case
# the process' output buffer fills up and it hangs waiting for someone to read
# its output.  This could cause a deadlock.
my $pid;
defined($pid = fork()) or die "fork: $!";

if (!$pid) {
    # This is the child.

    # Close handle to process' stdout; the child doesn't need it.
    close READER;

    # Write out some data.  Change this to print out your data.
    print WRITER $words[rand(@words)], " " for (1..100000);

    # Then close the handle to the process' stdin.
    close WRITER;
    # Terminate the child.
    exit;
}

# Parent closes its handle to the process' stdin immediately!  As long as one
# process has an open handle, the program on the receiving end of the data will
# never see EOF and may continue waiting.
close WRITER;

# Read in data from the process.  Change this to whatever you need to do to
# process the incoming data.
print "READ: $_" while (<READER>);

# Close the handle to the process' stdin.  After this call, the process should
# be finished executing and will terminate on its own.
close READER;

答案 1 :(得分:1)

如果它只接受文件,则让它打开“/ proc / self / fd / 0”,这与STDIN相同。其余的,请参阅cdhowies answer。

答案 2 :(得分:1)

如果您只想将程序中的STDOUT传输到其他程序的STDIN,则可以通过标准Perl open命令执行此操作:

open (CMD, "|$command") or die qq(Couldn't execute $command for piping);

然后,要将数据发送到此命令,您只需使用print语句:

print CMD $dataToCommand;

然后,您最终使用close语句关闭管道:

close (CMD);

PERL HINT

Perl有一个名为perldoc的命令,它可以为您提供系统上安装的任何Perl函数或Perl模块的文档。要获取有关open命令的更多信息,请键入:

$ perldoc -f open

-f说这是一个Perl函数

如果你正在做cdhowie在他的回答中所说的话(你正在产生一个过程,然后阅读并写入该过程),你将需要IPC::Open2。要获取有关IPC::Open2模块的信息,请键入:

$ perldoc IPC::Open2