2010-11-25 18 views
32

Ruby hat zwei Möglichkeiten, auf die Standardeingabe zu verweisen: Die STDIN Konstante und die $stdin globale Variable.

Abgesehen von der Tatsache, dass ich ein anderes IO Objekt $stdin zuweisen kann, weil es keine Konstante (zum Beispiel vor Forking IO in meinen Kindern Redirect), was ist der Unterschied zwischen STDIN und $stdin? Wann sollte ich jedes in meinem Code verwenden?

Wenn ich neu zuweisen $stdin, wirkt sich das auf STDIN?

Und gilt das auch für STDOUT/ und STDER/$stderr?

+2

'$ stdin' ist hässlicher. –

Antwort

35

Wenn $stdin neu zugewiesen wird, ist STDIN nicht betroffen. Ebenso ist $stdin nicht betroffen, wenn STDIN neu zugewiesen wird (was durchaus möglich ist (wenn auch sinnlos), aber eine Warnung erzeugt). Wenn jedoch keine der beiden Variablen neu zugewiesen wurde, zeigen beide auf dasselbe IO-Objekt, so dass das Aufrufen von reopen¹ auf einer die andere betrifft.

Alle eingebauten Ruby-Methoden verwenden $< (a.k.a. ARGF), um Eingaben zu lesen. Wenn ARGV leer ist, liest ARGF aus $stdin. Wenn Sie also $stdin neu zuweisen, wirkt sich dies auf alle integrierten Methoden aus. Wenn Sie STDIN neu zuweisen, hat dies keine Auswirkungen, es sei denn, eine Drittanbietermethode verwendet STDIN.

In Ihrem eigenen Code sollten Sie $stdin verwenden, um mit den integrierten Methoden zu konsistent zu sein².

¹ reopen ist eine Methode, die ein IO-Objekt in einen anderen Stream oder eine Datei umleiten kann. Sie können es jedoch nicht verwenden, um ein IO an ein StringIO umzuleiten, sodass es nicht alle Anwendungsfälle für die Neuzuweisung von $stdin beseitigt.

² Sie können natürlich auch $</ARGF verwenden noch mehr im Einklang mit den integrierten Methoden zu sein, aber die meiste Zeit Sie wollen nicht das ARGF Verhalten, wenn Sie explizit den stdin-Stream unter Verwendung von .

+0

Ich bin mir ziemlich sicher, dass die integrierten Methoden '$ <' (den Standard-Eingabestream) und '$>' (den Standard-Ausgabestream) und weder '$ stdin' /' STDIN' noch '$ stdout' /' verwenden STDOUT'. In der Tat, das ist so ziemlich der ganze Sinn von '$ <' and '$>': dass Sie die Eingabe und Ausgabe von Methoden wie 'Kernel # puts' * ohne * Auswirkungen auf stdin/stdout umleiten können. –

+3

@ Jörg: Du hast Recht, dass sie '$ <' and '$>' verwenden, das werde ich korrigieren. Aber Sie haben mit Ihrem zweiten Punkt nicht Recht: '$>' und '$ stdout' sind Aliase, also wird das Neuzuweisen des einen den anderen beeinflussen (anders als STDOUT, das unberührt bleibt). '$ <' ist dasselbe wie 'ARGF', wobei beide nicht neu zugewiesen werden können.Die Neuzuweisung von '$ stdin' * wirkt sich jedoch auf' $ <'und' ARGF' aus, da 'ARGF' von' $ stdin' liest, wenn 'ARGV' leer ist. – sepp2k

+2

Sie lernen jeden Tag etwas Neues ... –

0

STDERR und $ stderr zeigen zunächst auf die gleiche Sache; Sie können die globale Variable neu zuweisen, aber Sie sollten sich nicht mit der Konstante anlegen. $ stdin und STDIN, $ stdout und STDOUT Paare sind ebenfalls.

Ich musste STDERR ein paar Mal als eine Alternative zu Affen-Patching einige Edelsteine ​​ändern Fehlermeldungen mit STDERR.puts ausgeben. Wenn Sie STDERR = $ stdout neu zuweisen, erhalten Sie eine Warnung, während STDERR.reopen ('nul', 'w') selbstverständlich ist.