2010-05-23 3 views
7

Der folgende Code funktioniert Art fein:Wie bekomme ich die Ausgabe von einer Perl-Pipe, wie sie verfügbar ist?

open(PIPE, '-|', 'ant'); 
for(<PIPE>) { 
    print; 
} 

Allerdings ist es nicht tun, was ich will. Da der Ant-Build 5 Minuten dauern kann, möchte ich die Ausgabe Zeile für Zeile sehen. Stattdessen erhalte ich die gesamte Eingabe am Ende des Prozesses.

Wenn Sie es mit dem Perl-Debugger betrachten, wartet Perl auf die 'for'-Anweisung, bis Ant beendet wird. Warum das?

Antwort

8

Nur der Vollständigkeit halber (Problem wie erwähnt in dem Kommentar zu Uri Antwort gelöst wurde) entstand das Problem, weil der for Ausdruck der <> Operator in Listenkontext (see) ausgewertet wird, äquivalent zu den folgenden:

foreach $line (@lines = <PIPE>) { 
    print $line; 
} 

Im Listenkontext versucht der Operator <>alle Zeilen von seinem Eingang zu lesen, um ihn der Liste zuzuordnen - und die Eingabe kommt von einem Prozess, der blockiert wird, bis der Prozess endet. Erst danach kommt es in den Schleifenkörper.

Die alternative Syntax

while(<PIPE>) {   
    print; 
} 

entspricht stattdessen

while( $line = <PIPE>) { 
    print $line; 
} 

dh verbraucht er jede Zeile von dem Eingang in jeder Schleifeniteration, und das ist, was man in diesem Szenario tun möchte .

3

Ich glaube, das Problem ist Pufferung. Sie könnten die Dateihandle hot (ungepufferte) machen etwa so:

select PIPE; 
$| = 1; # the pipe is just a coincidence. that's the variable's name 
select STDOUT; # select it back 

Diese Pufferung für PIPE deaktivieren sollte. Ich lese über so etwas in Learning Perl, 5th. Siehe auch this. Sie sollten wahrscheinlich auch sicherstellen, dass die Pufferung an keinem anderen Ort stattfindet.

EDIT: das OP geschrieben, dass die für mit während ersetzt das Problem gelöst

Ich glaube, ich verstehe jetzt. while ruft jede Zeile und führt die Schleife, während for wirkt wie foreach und zuerst erhält alle Zeilen (es benötigt Listenkontext) und dann Schleifen über die Zeilen.

+7

Pufferung ist wahrscheinlich das Problem, aber der problematische Puffer ist auf der Seite von Ant, nicht von Perl. Sie müssen die Pufferung nur für Ausgabepipel und nicht für Pipelines deaktivieren.Sie müssen einen Weg finden, um Ant zu sagen, dass es seine Ausgabe nicht puffern soll. Sie können das Problem nicht auf der Perl-Seite beheben. – cjm

2

Es gefunden. Das Problem ist mit der 'for' Aussage.

Der folgende Code funktioniert erwartet als

open(PIPE, '-|', 'ant'); 
while(<PIPE>) {   # replacing 'for' with 'while' 
    print; 
} 

Ich weiß nicht den Grund, aber jetzt ist es funktioniert.

+2

Um zu verstehen, warum, siehe http://stackoverflow.com/questions/585341/ – Joe

+0

Wenn Sie Ihre eigene Frage beantwortet haben, ist es eine gute Idee, die ursprüngliche Frage zu bearbeiten und die Antwort hinzuzufügen, anstatt eine Antwort zu posten. –

+2

@Barry Brown posten Sie Ihre eigene Antwort und akzeptieren Sie es, wenn niemand eine bessere Antwort gibt (heh) Praxis auf SO. http://meta.stackexchange.com/questions/12513/stackoverflow-should-i-answer-my-own-question-or-not – hobbs

Verwandte Themen