如何在 perl 中为反引号加载 STDIN(不写入临时文件)

Posted

技术标签:

【中文标题】如何在 perl 中为反引号加载 STDIN(不写入临时文件)【英文标题】:How to load STDIN for a backtick in perl (without writing to a temp file) 【发布时间】:2012-04-20 16:31:18 【问题描述】:

我正在执行一个系统命令,并且想要 (1) 为系统命令预加载 STDIN 并 (2) 从命令中捕获 STDOUT。

根据here,我知道我可以做到这一点:

open(SPLAT, "stuff")   || die "can't open stuff: $!";
open(STDIN, "<&SPLAT") || die "can't dupe SPLAT: $!";
print STDOUT `sort`;

这使用当前定义的 STDIN 作为排序的 STDIN。如果我将数据保存在文件中,那就太好了,但我将它保存在变量中。有没有办法在执行系统命令之前将变量的内容加载到 STDIN 中?比如:

open(STDIN, "<$myvariable"); # I know this syntax is not right, but you get the idea
print STDOUT `sort`;

可以不使用临时文件来完成吗?另外,我在 Windows 中,所以不推荐使用 Open2,我听说。

谢谢。

【问题讨论】:

【参考方案1】:

没有理由不在 Windows 上使用 open2。也就是说,open2open3 是相当低级的接口,因此它们通常不是任何平台上的最佳选择。

更好的选择包括IPC::Run 和IPC::Run3。 IPC::Run 比 IPC::Run3 强大一点,但后者使用起来更简单一些。

我可以推荐一下

use IPC::Run3 qw( run3 );
my $stdin = ...;
run3([ 'sort' ], \$stdin, \my $stdout);

它甚至会为你做错误检查。


但是既然你提到了open2

use IPC::Open2 qw( open2 );
my $stdin =...;
my $pid = open2(\local *TO_CHILD, \local *FROM_CHILD, 'sort');
print TO_CHILD $stdin;
close TO_CHILD;
my $stdout = '';
$stdout .= $_ while <FROM_CHILD>;
waitpid($pid);
die $? if $?;

【讨论】:

谢谢。我真的很喜欢Run3 的简单性,尤其是因为我不需要一堆功能。非常紧凑。 您是否知道 ActiveState 是否具有与 IPC::Run3 等价的功能?我在他们的 ppm 列表中没有看到它。也许是IPC::Cmd 要么有,要么没有。不同的模块是不等价的。也就是说,它在 AS 的 5.14.2 32 位 repo 中可用,您始终可以使用 cpan IPC::Run3 安装它。【参考方案2】:

也许IPC::Open2 在 15 年前在 Windows 上运行得不是很好,但我不认为你现在会遇到任何麻烦。

use IPC::Open2;
my $pid = open2( \*SORT_OUT, \*SORT_IN, 'sort' );
print SORT_IN $sort_input;  # or  @sort_input
close SORT_IN;
print "The sorted output is: ", <SORT_OUT>;
close SORT_OUT;

【讨论】:

感谢您让我直接了解 Open2 在 Windows 上的可用性。好答案。 +1。

以上是关于如何在 perl 中为反引号加载 STDIN(不写入临时文件)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Perl 中测试 STDIN 而不会阻塞?

如何在 Perl 中读取和写入大缓冲区到进程 stdin/stdout/stderr?

perl 第三弹 句柄

如何在 SQL 脚本中使用 Perl 变量(使用反引号)

在 Perl 中从 STDIN 捕获退出状态

为啥 STDIN 会导致我的 Perl 程序冻结?