如何使用标量作为perl中open3的输入
我有一个标量,我想输入到open3中作为输入。比如说如何使用标量作为perl中open3的输入,perl,reference,ipcopen3,Perl,Reference,Ipcopen3,我有一个标量,我想输入到open3中作为输入。比如说 my $sql = "select * from table;"; open( SQL, "<", \$sql ); my ($output); open3( '<&SQL', $output, $output, "mysql -h 127.0.0.1" ); 然后在另一个文件中: package Example::Runner; sub run { my ($in, $out, $err, @command
my $sql = "select * from table;";
open( SQL, "<", \$sql );
my ($output);
open3( '<&SQL', $output, $output, "mysql -h 127.0.0.1" );
然后在另一个文件中:
package Example::Runner;
sub run {
my ($in, $out, $err, @command) = @_;
open3( ?, $out, $err, "mysql -h 127.0.0.1" );
}
问题是,在Example::Runner
中,我有一个可以从
中读取的参考,但我需要的是可以在前面加上前缀的东西。fileno($err_handle):未定义,
@命令
);
返回($^O=~/MSWin32/)_win_open3(@args):_nix_open3(@args);
}
但是如果
$in_handle
是标量引用,它就不起作用。无论如何,这是一个很长的故事。open\$var
不起作用,因为它不创建子级可以读取的系统文件句柄
$ perl -E'open(my $fh, "<", \"abc") or die $!; say fileno($fh);'
-1
但这很危险。你正冒着陷入僵局的风险。(当您尝试向其STDIN发送大量[1]数据时,如果孩子尝试向STDOUT或STDERR发送大量[1]数据,则会发生死锁。)要避免此问题,您需要一个select
循环。这很难。你不想用这么低级的东西。使用或代替open3
,因为他们会为你做所有的脏活
use IPC::Run3 qw( run3 );
run3($shell_cmd, \$sql, \my $out, \my $err);
更好的是,避免不必要的外壳:
run3([ $prog, @args ], \$sql, \my $out, \my $err);
但是,为什么要使用为人使用而设计的客户机作为界面呢?您可能应该使用
我不太明白。你为什么不能给它一个手柄,然后打印到那个手柄上<代码>我的$pid=open3(\*SQL,$output,$output,“mysql-H127.0.0.1”);如果($pid){print SQL();close(SQL);}或保持原始的
SQL
并打开(\*SQL2,$output,$output,…);打印SQL2;关闭SQL2@hepcat72,@mob,我试图简化本例中的问题,但原因是它必须在命令开始运行之前存在,或者我用来处理OUT和ERR(以及in ish)的IO::Select
变得不可靠。(这是针对IO::Open3::Callback::safe\u open\u 3
)…IPC::Open3无法做到这一点。使用IPC::Run可以提供一种更灵活的界面,该界面还支持输入/输出的标量和函数。也许我不太明白您到底想做什么,但为什么不使用DBI呢?我过去曾研究过IPC::Run
,但它阻碍了我。至于为什么不使用DBI
,我正在尝试运行任意SQL脚本。一个足够简单的脚本可以在<代码>上进行拼凑和拆分代码>和循环,但如果存在函数定义或分隔符切换,或任何其他特定于db的操作,则会中断…恰恰相反,IPC::Run会走极端以支持Windows。但是如果没有fork
和select
,它会遇到很多障碍。(select
仅适用于Windows中的套接字。)
sub safe_open3_with {
my ($in_handle, $out_handle, $err_handle, @command) = @_;
my @args = (
$in_handle ? '<&' . fileno( $in_handle ) : undef,
$out_handle ? '>&' . fileno( $out_handle ) : undef,
$err_handle ? '>&' . fileno( $err_handle ) : undef,
@command
);
return ( $^O =~ /MSWin32/ ) ? _win_open3(@args) : _nix_open3(@args);
}
$ perl -E'open(my $fh, "<", \"abc") or die $!; say fileno($fh);'
-1
pipe(local *CHILD_STDIN, local *TO_CHILD)
or die("Can't create pipe: $!\n");
my $pid = open3($cmd, '<&CHILD_STDIN', local *FROM_CHILD, undef);
print(TO_CHILD do { local $/; <$in> });
close(TO_CHILD);
use IPC::Run3 qw( run3 );
run3($shell_cmd, \$sql, \my $out, \my $err);
run3([ $prog, @args ], \$sql, \my $out, \my $err);