2016-10-21 1 views
0

Ich hätte gerne Hilfe bei der Berechnung dieses speziellen Codierungsproblems.Perl respektiert '<' als reguläres Zeichen, eher als Ausgabeumleitung

Ich habe ein Perl-Skript (# 1), das ein anderes Perl-Skript (# 2) aufruft. In # 1 rufe ich # 2 an, um seine Ausgabe auch in eine Protokolldatei umzuleiten. like so

my @command = ('downloadImage', '-url', $url, '>', $log); 

dieser Befehl läuft gut, wenn es auf dem Terminal ausgeführt wird. Muss ich eine andere Art von Sonderzeichen verwenden, um Perl mitzuteilen, dass es sich bei der Ausgabeumleitung nicht um ein normales Zeichen handelt?

Ich betreibe es als:

system(@command); 
+0

Wie ausführen Sie '@ command'? – Schwern

Antwort

4

gehe ich davon aus der vollständige Code ist:

my @command = ('downloadImage', '-url', $url, '>', $log); 
system @command; 

system verfügt über zwei Modi. system $command wird $command in der Shell ausgeführt.

# This will write 'foo' to the file 'bar' 
system "echo foo > bar"; 

system @command ist wirklich system $program, @args. Es wird die Shell umgehen und die $program mit @args ausführen.

# This will print 'foo > bar' 
system "echo", "foo", ">", "bar" 

Wenn Sie also eine solche Ausgabeumleitung machen möchten, können Sie @ command zusammenfügen.

system join " ", @command; 

Aber das kann in Shell-Zitat Probleme führen. Es ist sicherer, schneller und portabler, die Umleitung selbst in Perl mit einer piped open vorzunehmen.

use strict; 
use warnings; 
use autodie; 

open my $echo, "-|", "echo", "foo"; 
open my $log, ">", "some.log"; 

print {$log} <$echo>; 
+2

Tipp: 'print {$ log} $ _ während <$echo>;' reduziert den Speicheraufwand. – ikegami

3

system('downloadImage', '-url', $url, '>', $log) 

in Perl zu tun, ist die gleiche wie

'downloadImage' '-url' "$url" '>' "$log" 

in der Shell zu tun. Dieser führt downloadImage mit vier Argumenten aus, von denen eines > ist. Der Shell-Befehl Sie versuchen, ist die folgende auszuführen:

'downloadImage' '-url' "$url" > "$log" 

Wenn Sie diese Shell-Befehl ausführen möchten, müssen Sie zunächst eine Shell benötigen. Hier finden Sie, wie Sie dies erreichen sollte:

jedoch
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); 

, es gibt viele Nachteile, um eine Schale mit. Hier sind einige Alternativen:

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); 
} 

oder

use IPC::Run3 qw(run3); 

my @cmd = ('downloadImage', '-url', $url); 

run3(\@cmd, \undef, $log); 

oder

use IPC::Run qw(run); 

my @cmd = ('downloadImage', '-url', $url); 

run(\@cmd, '<', '/dev/null', '>', $log); 
+1

(Ich habe nur IPC :: Open3 eingeschlossen, weil es mit Perl gebündelt ist. Es ist ehrlich gesagt zu niedrig für die meisten Anwendungen.) – ikegami

Verwandte Themen