在 Perl 脚本的中间,有一个我要执行的系统命令。 我有一个字符串,其中包含需要输入到 stdin 的数据(该命令仅接受来自 stdin 的输入),并且我需要捕获写入 stdout 的输出。 我研究了 Perl 中执行系统命令的各种方法,open
函数似乎就是我所需要的,只不过它看起来只能捕获 stdin 或 stdout,而不能同时捕获两者。
目前,我最好的解决方案似乎是使用 open,将 stdout 重定向到临时文件,并在命令完成后从文件中读取。 有更好的解决方案吗?
In the middle of a Perl script, there is a system command I want to execute. I have a string that contains the data that needs to be fed into stdin (the command only accepts input from stdin), and I need to capture the output written to stdout. I've looked at the various methods of executing system commands in Perl, and the open
function seems to be what I need, except that it looks like I can only capture stdin or stdout, not both.
At the moment, it seems like my best solution is to use open
, redirect stdout into a temporary file, and read from the file after the command finishes. Is there a better solution?
发布评论
评论(9)
IPC::Open2/3 很好,但我发现通常我真正需要的是 IPC: :Run3,它以最小的复杂性很好地处理了简单的情况:
该文档将 IPC::Run3 与其他替代方案进行了比较。 即使您不决定使用它,也值得一读。
IPC::Open2/3 are fine, but I've found that usually all I really need is IPC::Run3, which handles the simple cases really well with minimal complexity:
The documentation compares IPC::Run3 to other alternatives. It's worth a read even if you don't decide to use it.
perlipc 文档 涵盖了许多实现此目的的方法,包括 IPC::Open2 和 IPC: :打开3。
The perlipc documentation covers many ways that you can do this, including IPC::Open2 and IPC::Open3.
在脚本顶部的某个位置,包含一行
That will include the required module,通常默认情况下随大多数 Perl 发行版一起安装。 (如果没有,可以使用 CPAN 安装它。)然后,不使用 open,而是调用:
您可以通过将数据发送到 $cmd_in 来将数据发送到命令,然后通过从 $cmd_out 读取来读取命令的输出。
如果您还希望能够读取命令的 stderr 流,则可以使用 IPC::Open3 模块。
Somewhere at the top of your script, include the line
That will include the necessary module, usually installed with most Perl distributions by default. (If you don't have it, you could install it using CPAN.) Then, instead of open, call:
You can send data to your command by sending it to $cmd_in and then read your command's output by reading from $cmd_out.
If you also want to be able to read the command's stderr stream, you can use the IPC::Open3 module instead.
IPC::Open3 可能会做你想做的事。 它可以捕获 STDERR 和 STDOUT。
http://metacpan.org/pod/IPC::Open3
IPC::Open3 would probably do what you want. It can capture STDERR and STDOUT.
http://metacpan.org/pod/IPC::Open3
我最近发现的一个非常简单的方法是 IPC::Filter 模块。 它可以让您非常直观地完成这项工作:
请注意,如果您向它传递一个列表,它如何调用您的命令,而无需通过 shell。 它还可以合理地处理常见实用程序的错误。 (失败时,它
死亡
,使用 STDERR 中的文本作为错误消息;成功时,STDERR 被丢弃。)当然,它不适合大量数据,因为它没有提供任何方法进行任何流处理; 此外,错误处理可能不够精细,无法满足您的需求。 但它使许多简单的情况变得非常非常简单。
A very easy way to do this that I recently found is the IPC::Filter module. It lets you do the job extremely intuitively:
Note how it invokes your command without going through the shell if you pass it a list. It also does a reasonable job of handling errors for common utilities. (On failure, it
die
s, using the text from STDERR as its error message; on success, STDERR is just discarded.)Of course, it’s not suitable for huge amounts of data since it provides no way of doing any streaming processing; also, the error handling might not be granular enough for your needs. But it makes the many simple cases really really simple.
我想你想看看 IPC: :打开2
I think you want to take a look at IPC::Open2
有一个特殊的 perl 命令,
可以在以下位置找到更多信息: http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html
There is a special perl command for it
More info can be found on: http://sunsite.ualberta.ca/Documentation/Misc/perl-5.6.1/lib/IPC/Open2.html
如果您不想包含额外的软件包,您可以这样做,
这与您的建议相反,但也应该可行。
If you do not want to include extra packages, you can just do
which is the contrary of what you suggested, but should work also.
如果我只期望单行输出或想要将结果拆分为换行符以外的其他内容,我总是这样做:
如果要处理多行响应,请将结果作为数组获取:
I always do it this way if I'm only expecting a single line of output or want to split the result on something other than a newline:
If you want to deal with a multi-line response, get the result as an array: