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

有没有办法将数据从Perl传输到Unix命令行实用程序,perl,bash,unix,Perl,Bash,Unix,我有一个来自第三方的命令行实用程序(它很大,是用Java编写的),我一直在使用它来帮助我处理一些数据。此实用程序需要一个以行分隔的文件中的信息,然后将处理后的数据输出到标准输出 在我的测试阶段,我可以编写一些Perl来创建一个包含要处理的信息的文件,然后将该文件发送给这个第三方实用程序,但随着我即将将此代码投入生产,我真的更喜欢直接将数据管道传输到这个实用程序,而不是先将数据写入文件,因为这样可以节省将不需要的信息写入磁盘的开销。我最近在这个板上问过如何在Unix中实现这一点,但后来意识到直接从

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

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

系统(bin/someapp执行操作——选项1某些值——在数据中输入$piped)

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

bin/someapp执行操作——选项1一些值——输入一些文件


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

如果我正确地阅读了您的问题,那么您希望生成一个进程,并且能够同时写入其stdin和读取其stdout。如果是这样的话,那么这正是你所需要的。(另请参见,您还需要读取流程的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;
#/usr/bin/perl
严格使用;
使用警告;
使用IPC::Open2;
#示例数据——忽略此项。
我的@words=qw(敏捷的棕色狐狸跳过了懒狗);
#自动获取子进程。这在分叉时很重要。
$SIG{'CHLD'}='IGNORE';
#在这里生成外部进程。将此更改为您需要的流程。
open2(*READER,*WRITER,“wc-c”)或die“wc-c:$!”;
#进入子进程。子进程将写入数据,而
#父进程从进程读回数据。我们需要用叉子以防万一
#进程的输出缓冲区已满,它将挂起,等待有人读取
#它的输出。这可能会导致僵局。
我的$pid;
定义($pid=fork())或死“fork:$!”;
如果(!$pid){
#这就是那个孩子。
#关闭进程stdout的句柄;子进程不需要它。
密切阅读;
#写出一些数据。将此更改为打印数据。
印刷撰稿人$words[rand(@words)],“”用于(1..100000);
#然后关闭进程stdin的句柄。
亲密的作家;
#终止孩子的生命。
出口
}
#父进程立即关闭其进程stdin的句柄!只要一个
#进程有一个打开的句柄,接收端的程序将
#从未见过EOF,可能会继续等待。
亲密的作家;
#从进程中读入数据。将此更改为您需要执行的任何操作
#处理传入的数据。
打印“READ:$\”而不打印();
#关闭进程stdin的句柄。在这个调用之后,进程应该
#已完成执行,并将自行终止。
密切阅读;

如果它只接受文件,就让它打开“/proc/self/fd/0”,这与标准文本相同。其余内容,请参见cdhowies答案。

如果您只想将标准输出从您的程序导入其他程序的标准输入,则可以通过标准的Perl
open
命令:

open (CMD, "|$command") or die qq(Couldn't execute $command for piping);
然后,要将数据发送到此命令,只需使用
print
语句:

print CMD $dataToCommand;
close (CMD);
最后,使用
close
语句关闭管道:

print CMD $dataToCommand;
close (CMD);
PERL提示

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

$ perldoc -f open
-f
表示这是一个Perl函数

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

$ perldoc IPC::Open2

该工具是否接受STDIN上的数据?或者
/dev/STDIN
,它可能是指向
/proc/self/fd/0
的符号链接。最近的这个问题显示了IPC::Open3的一些工作示例。我想这正是我想要的,但在我的示例中,我很难弄清楚如何使用它。你有没有可能粘贴与我文章中的示例更相似的示例代码?非常感谢!这正是我想要的,现在对我来说很有意义。你真棒!