Perl 将 '<' 视为常规字符,而不是输出重定向
Posted
技术标签:
【中文标题】Perl 将 \'<\' 视为常规字符,而不是输出重定向【英文标题】:Perl is respecting '<' as a regular character rather an output redirectionPerl 将 '<' 视为常规字符,而不是输出重定向 【发布时间】:2016-10-21 17:29:28 【问题描述】:我需要一些帮助来解决这个特殊的编码问题。
我有一个调用另一个 perl 脚本 (#2) 的 perl 脚本 (#1)。在 #1 中,我调用 #2 也将其输出重定向到日志文件。像这样
my @command = ('downloadImage', '-url', $url, '>', $log);
此命令在终端上运行时运行良好。 我是否必须使用其他类型的特殊字符来告诉 perl > 是输出重定向而不仅仅是一些常规字符?
我是这样运行的:
system(@command);
【问题讨论】:
你是如何执行@command
的?
【参考方案1】:
我假设完整的代码是:
my @command = ('downloadImage', '-url', $url, '>', $log);
system @command;
system
有两种模式。 system $command
将在 shell 中运行 $command
。
# This will write 'foo' to the file 'bar'
system "echo foo > bar";
system @command
真的是system $program, @args
。它将绕过 shell 并运行 $program
和 @args
。
# This will print 'foo > bar'
system "echo", "foo", ">", "bar"
所以如果你想像这样进行输出重定向,你可以将@command 一起加入。
system join " ", @command;
但这可能会遇到 shell 引用问题。在 Perl 中使用 piped open 自己进行重定向更安全、更快、更便携。
use strict;
use warnings;
use autodie;
open my $echo, "-|", "echo", "foo";
open my $log, ">", "some.log";
print $log <$echo>;
【讨论】:
提示:print $log $_ while <$echo>;
减少了内存开销。【参考方案2】:
在做
system('downloadImage', '-url', $url, '>', $log)
在 Perl 中是一样的
'downloadImage' '-url' "$url" '>' "$log"
在外壳中。这将使用四个参数执行downloadImage
,其中一个是>
。您尝试执行的 shell 命令如下:
'downloadImage' '-url' "$url" > "$log"
如果你想执行那个 shell 命令,你首先需要一个 shell。以下是您应该如何实现这一目标:
use String::ShellQuote qw( shell_quote );
my @cmd = ('downloadImage', '-url', $url);
my $shell_cmd = shell_quote(@cmd) . ' >' . shell_quote($log);
system($shell_cmd); # Short for system('/bin/sh', '-c', $shell_cmd);
但是,使用 shell 有很多缺点。以下是一些替代方案:
use IPC::Open3 qw( open3 );
my @cmd = ('downloadImage', '-url', $url);
open(local *CHILD_STDIN, '<', '/dev/null')
or die("Can't open \"/dev/null\": $!\n");
open(local *CHILD_STDOUT, '>', $log)
or die("Can't create \"$log\": $!\n");
my $pid = open3('<&CHILD_STDIN', '>&CHILD_STDOUT', '>&STDERR', @cmd);
waitpid($pid, 0);
或
use IPC::Run3 qw( run3 );
my @cmd = ('downloadImage', '-url', $url);
run3(\@cmd, \undef, $log);
或
use IPC::Run qw( run );
my @cmd = ('downloadImage', '-url', $url);
run(\@cmd, '<', '/dev/null', '>', $log);
【讨论】:
(我只包括了 IPC::Open3,因为它与 Perl 捆绑在一起。老实说,对于大多数用途来说,它的级别太低了。)以上是关于Perl 将 '<' 视为常规字符,而不是输出重定向的主要内容,如果未能解决你的问题,请参考以下文章