2016-04-20 2 views
0

Angenommen, I-Code haben folgende Dateihandle zu öffnen:

open my $fh, "command1 | command2 |"; 

I command1 Ausgang gefunden, dass command2 nicht gut umgehen kann, so versuche ich, ein Perl-Filter zwischen command1 und command2 einzufügen, mit ihnen zu beschäftigen:

use Config; 
open my $fh, "command1 | $Config{perlpath} -ple 'blah blah' | command2 |"; 

Meine Fragen sind:

  1. Ist es OKzu verwendenim Systemanruf direkt?
  2. Aufruf eigene Perl binär scheint Nüsse. Gibt es bessere Lösungen? direkt

Dank

+1

Kürzere Version von '$ Config {perlpath}': ['$^X'] (https: // metacpan.org/pod/perlvar # EXECUTABLE_NAME) – mob

+0

Auf jeden Fall eine Sünde. Aber ein geringfügiger. – mob

Antwort

1

Ist es OK Config $ verwenden {perlpath} in Systemaufruf?

Relativ. Es ist ungefähr so ​​portabel wie der Rest Ihres Codes (der bereits davon abhängt, auf etwas Unix-ish zu laufen). Es gibt einige Sicherheitsbedenken, aber ich würde sagen, nicht sehr groß, weil jemand, der den Wert dieser Variablen beeinflussen kann, bereits Spielraum hat, Chaos zu verursachen. $^X ist in dieser Hinsicht wahrscheinlich sicherer. Sie können es aus Sicherheitsgründen mit String::ShellQuote angeben, da Sie die Shell in der Mitte einer Pipeline nicht umgehen können.

Aufruf eigenen Perl binär scheint Nüsse. Gibt es bessere Lösungen?

Hängt von Ihrer Definition von "besser" ab. Es gibt definitiv einen anderen Weg, der sowohl als auch command2 separat laufen lässt, die Ausgabe command1 in Ihrem ursprünglichen Perl-Prozess verarbeitet, es an command2 übergibt und command2 's-Ausgabe liest. Sie müssen jedoch vorsichtig sein, wie Sie es tun. Es gibt zwei sichere Wege.

Der erste Weg ist einfacher, aber dauert mehr Zeit und Speicher: run zuerst, lesen und verarbeiten Sie alle seine Ausgabe in eine Zeichenfolge, dann command2 läuft die gepufferte Ausgabe als Eingabe. Der beste Weg, dies zu tun ist, IPC::Run zu verwenden, um command2 's Eingabe und Ausgabe (und möglicherweise beide Befehle, nur für die Konsistenz) zu behandeln; Wenn Sie versuchen, nur alle Daten auf command2 's Eingabe-Handle zu drucken und dann alle Ausgaben zu lesen, können Sie Deadlock, aber IPC :: Run wird Lesen und Schreiben verschachteln, wenn nötig hinter den Kulissen, und Ihnen eine nette einfache Schnittstelle. Die zweite Möglichkeit ist komplizierter, aber näher am Verhalten des Originals: Sie benötigen eine Art asynchronen Rahmen wie IO::Async oder POE, verwenden ihre Klassen für die Prozesskonstruktion und richten Handler ein, um zwischen ihnen zu kommunizieren, filtern Sie, und sammle die Ausgabe.

Here's ein getestetes Spielzeug Beispiel (das ist, weil es ein paar Screenfuls Code ist), die das Äquivalent von ls | perl -pe '$_ = uc' | rev tut, außer mit dem mittleren Teil der Pipeline im Parent-Perl-Prozess ausgeführt wird. Sie dürfen es nie benutzen, aber ich dachte, es wäre eine Illustration wert.

Verwandte Themen