有没有办法将数据从Perl传输到Unix命令行实用程序
我有一个来自第三方的命令行实用程序(它很大,是用Java编写的),我一直在使用它来帮助我处理一些数据。此实用程序需要一个以行分隔的文件中的信息,然后将处理后的数据输出到标准输出 在我的测试阶段,我可以编写一些Perl来创建一个包含要处理的信息的文件,然后将该文件发送给这个第三方实用程序,但随着我即将将此代码投入生产,我真的更喜欢直接将数据管道传输到这个实用程序,而不是先将数据写入文件,因为这样可以节省将不需要的信息写入磁盘的开销。我最近在这个板上问过如何在Unix中实现这一点,但后来意识到直接从Perl模块中运行它会非常方便。也许是这样的:有没有办法将数据从Perl传输到Unix命令行实用程序,perl,bash,unix,Perl,Bash,Unix,我有一个来自第三方的命令行实用程序(它很大,是用Java编写的),我一直在使用它来帮助我处理一些数据。此实用程序需要一个以行分隔的文件中的信息,然后将处理后的数据输出到标准输出 在我的测试阶段,我可以编写一些Perl来创建一个包含要处理的信息的文件,然后将该文件发送给这个第三方实用程序,但随着我即将将此代码投入生产,我真的更喜欢直接将数据管道传输到这个实用程序,而不是先将数据写入文件,因为这样可以节省将不需要的信息写入磁盘的开销。我最近在这个板上问过如何在Unix中实现这一点,但后来意识到直接从
系统(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答案。如果您只想将标准输出从您的程序导入其他程序的标准输入,则可以通过标准的Perlopen
命令:
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的一些工作示例。我想这正是我想要的,但在我的示例中,我很难弄清楚如何使用它。你有没有可能粘贴与我文章中的示例更相似的示例代码?非常感谢!这正是我想要的,现在对我来说很有意义。你真棒!