Perl系统命令,多个参数输出到文件

LKr*_*mer 1 perl

我需要使用以下形式调用系统命令:

system( $cmd, @args );
Run Code Online (Sandbox Code Playgroud)

当我将@args定义为

my @args = ( "input1", "input2", ">", "file.out" );
Run Code Online (Sandbox Code Playgroud)

">"和"file.out"并不像我希望的那样被解释.如何将此形式的系统命令的输出发送到文件?

ike*_*ami 8

这会将四个参数传递给程序,就像在shell中执行以下操作一样:

 prog "input1" "input2" ">" "file.out"
Run Code Online (Sandbox Code Playgroud)

您无法在不使用shell的情况下指示shell重定向输出!

以下解决方案假设:

my $prog = 'cat';
my @args = ( 'input1', 'input2' );
my $out_qfn = 'file.out';
Run Code Online (Sandbox Code Playgroud)

以下解决方案都缺少一些错误检查.

解决方案1

使用shell执行重定向和转义.

system('/bin/sh', '-c', '"$@" > "$0"', $out_qfn, $prog, @args);
Run Code Online (Sandbox Code Playgroud)

解决方案2

使用shell执行重定向,并使用Perl执行转义.

use String::ShellQuote qw( shell_quote );

my $cmd = shell_quote($prog, @args) . " >".shell_quote($out_qfn);
system('/bin/sh', '-c', $cmd);
Run Code Online (Sandbox Code Playgroud)

最后一行简化为

system($cmd);
Run Code Online (Sandbox Code Playgroud)

解决方案3

避免使用shell.使用Perl执行重定向.

# This isn't safe if @args is empty.

open(my $out_fh, '>', $out_qfn)
   or die("Can't create output file \"$out_qfn\": $!\n");

open(my $pipe, '-|', $prog, @args)
   or die $!;

while (<$pipe>) {
   print($out_fh $_);
}

close($fh);
Run Code Online (Sandbox Code Playgroud)

要么

# This isn't safe if @args is empty.

use IPC::Open3 qw( open3 );

{
   open(local *CHILD_STDIN, '<', '/dev/null')
      or die $!;

   open(local *CHILD_STDOUT, '>', $out_qfn)
      or die("Can't create output file \"$out_qfn\": $!\n");

   my $pid = open3('<&CHILD_STDIN', '>&CHILD_STDOUT', '>&STDERR', $prog, @args);
   waitpid($pid, 0);
}
Run Code Online (Sandbox Code Playgroud)

要么

use IPC::Run3 qw( run3 );

run3([ $prog, @args ], \undef, $out_qfn);
Run Code Online (Sandbox Code Playgroud)

要么

use IPC::Run qw( run );

run([ $prog, @args ], \undef, $out_qfn);
Run Code Online (Sandbox Code Playgroud)