2009-02-12 7 views
8

Ich habe eine Codezeile entlang der Linien von:

print $somehash{$var}{fh} "foo"; 

Der Hash enthält die Dateikennung ein paar Stufen nach unten. Der Fehler ist:

String found where operator expected at test.pl line 10, near "} "foo"" 

ich es, indem Sie diese beheben können:

my $fh = $somehash{$var}{fh}; 
print $fh "foo"; 

... aber gibt es einen Einzeiler?

+0

Sie können "sagen", was Sie wollen. Es macht es zu arbeiten, das ist knifflig :) –

Antwort

23

siehe http://perldoc.perl.org/functions/print.html

Beachten Sie, dass, wenn Sie Dateihandies in einem Array sind speichern, oder wenn Sie unter Verwendung eines beliebigen anderen Ausdruck mehr komplexer als eine skalare Variable es abrufen, Sie haben stattdessen einen Block Zurückführen der Dateikennung Wert verwenden: ...

in Ihrem cas So, e, würden Sie einen Block wie folgt verwenden:

print { $somehash{$var}{fh} } "foo"; 
+2

Ausgezeichnete Antwort, und nur um es konkret zu machen: print {$ someshash {$ var} {fh}} "foo"; – andy

+0

Guter Punkt @andy, ich habe die Antwort bearbeitet, um diese Codezeile einzuschließen. Bearbeitungen sind hier willkommen, versuchen Sie es beim nächsten Mal. – Flimm

10

Wenn Sie etwas anderes als eine einfache skalare als Dateihandle haben, können Sie die Referenzhalte die Dateikennung in Klammern wickeln müssen so Perl weiß, wie die Anweisung zu analysieren:

print { $somehash{$var}{fh} } $foo; 

Teil Perl Best Practices sagt immer Dateihandies in Klammern wickeln nur aus diesem Grund, obwohl ich nicht, dass nussig mit ihm zu tun bekommen.

Die Syntax ist seltsam, weil print eine indirekte Methode auf einem Dateihandle-Objekt ist:

method_name Object @arguments; 

Sie haben diese CGI.pm in der alten Schule gesehen könnten. Hier sind zwei indirekte Methodenaufrufe:

use CGI; 

my $cgi_object = new CGI 'cat=Buster&bird=nightengale'; 

my $value = param $cgi_object 'bird'; 

print "Indirect value is $value\n"; 

, dass fast funktioniert (siehe Schwern's answer about the ambiguity), solange sich das Objekt in einem einfachen Skalar ist. Allerdings, wenn ich die $cgi_object in einen Hash setzen, bekomme ich den gleichen Syntaxfehler, den Sie mit print bekommen haben. Ich kann die Klammern um den Hash-Zugriff legen, damit es funktioniert. Weiter mit dem vorherigen Code:

my %hash; 

$hash{animals}{cgi} = $cgi_object; 

# $value = param $hash{animals}{cgi} 'cat'; # syntax error 
$value = param { $hash{animals}{cgi} } 'cat'; 
print "Braced value is $value\n"; 

, die so nur auf den Pfeil-Notation für alles verwenden Sie stattdessen alle ein bisschen klobig ist:

my $cgi_object = CGI->new(...); 
$cgi_object->param(...); 

$hash{animals}{cgi}->param(...); 

Sie tun können, das gleiche mit Dateihandies, obwohl Sie die IO::Handle verwenden müssen Modul, damit es funktioniert:

use IO::Handle; 

STDOUT->print('Hello World'); 

open my($fh), ">", $filename or die ...; 
$fh->print(...); 

$hash{animals}{fh} = $fh; 

$hash{animals}{fh}->print(...); 
5

Die obigen Antworten sind alle korrekt. Der Grund, warum sie dort keinen vollen Ausdruck erlauben, ist print FH LIST ist schon ziemlich komische Syntax. Etwas Komplizierteres darin einzuführen, würde eine Menge mehrdeutiger Syntax einführen. Der Block entfernte diese Mehrdeutigkeit.

Um zu sehen, wohin dieser Wahnsinn führt, betrachten Sie den Horror, der indirekte Objekt-Syntax ist.

foo $bar; # Is that foo($bar) or $bar->foo()? Good luck! 
Verwandte Themen