web-dev-qa-db-ja.com

RubyのSTDINと$ stdinの違いは何ですか?

Rubyには、標準入力を参照する2つの方法があります。STDIN定数と、$stdinグローバル変数です。

別のIOオブジェクトを$stdinに割り当てることができるという事実は別として、定数ではないため(たとえば、リダイレクトをフォークする前にIO私の子供たち))、 STDIN$stdinの違いは?コードでそれぞれをいつ使用する必要があるのですか?

$stdinを再割り当てした場合、STDINに影響しますか?

そして、これはSTDOUT/$stdoutSTDER/$stderrにも当てはまりますか?

38
Ken Bloom

_$stdin_が再割り当てされても、STDINは影響を受けません。同様に、_$stdin_は、STDINが再割り当てされても影響を受けません(これは完全に可能ですが(無意味ですが)、警告が表示されます)。ただし、どちらの変数も再割り当てされていない場合は、両方が同じIOオブジェクトを指しているため、一方でreopen¹を呼び出すと、もう一方に影響します。

すべての組み込みRubyメソッドは_$<_(別名ARGF)を使用して入力を読み取ります。ARGVが空の場合、ARGFは_$stdin_から読み取るため、_$stdin_、これはすべての組み込みメソッドに影響します。STDINを再割り当てした場合、サードパーティのメソッドがSTDINを使用しない限り、効果はありません。

独自のコードでは、組み込みのメソッド²と一貫性を保つために_$stdin_を使用する必要があります。

¹reopenは、IOオブジェクトを別のストリームまたはファイルにリダイレクトできるメソッドです。ただし、これを使用してIOをStringIOにリダイレクトすることはできません。したがって、_$stdin_を再割り当てするすべてのユースケースが排除されるわけではありません。

²もちろん、組み込みメソッドとの一貫性をさらに高めるために_$<_/ARGFを使用することもできますが、ほとんどの場合、しないでくださいARGFの動作が必要です。 stdinストリームを明示的に使用します。

40
sepp2k

STDERRと$ stderrは、最初は同じものを指しています。グローバル変数を再割り当てすることはできますが、定数をいじってはいけません。 $ stdinとSTDIN、$ stdoutとSTDOUTのペアも同様です。

STDERR.putsでエラーメッセージを出力するいくつかのgemにモンキーパッチを適用する代わりに、STDERRを数回変更する必要がありました。 STDERR = $ stdoutで再割り当てすると、STDERR.reopen( 'nul'、 'w')が言うまでもなく警告が表示されます。

1
mtelis