Różnica między $ stdout i STDOUT w Rubim

89

Jaka jest różnica między $stdout(poprzedzonymi znakiem dolara) a STDOUT(wielkimi literami) w Rubim ? Podczas przekierowywania wyjścia, które powinno być używane i dlaczego? To samo dotyczy $stderri STDERR.

Edycja: właśnie znalazłem powiązane pytanie .

jrdioko
źródło
@theTinMan Somewhat to duplikat. Należy jednak zauważyć, że podczas gdy różnice między $stdouti STDOUTvs $stdini STDINsą symetryczne, różnice między $stdouti $>vs $stdini $<nie są.
skalee

Odpowiedzi:

108

$stdoutjest zmienną globalną, która reprezentuje bieżące standardowe wyjście. STDOUTjest stałą reprezentującą standardowe wyjście i zwykle jest wartością domyślną $stdout.

Ponieważ STDOUTjest to stała, nie należy jej ponownie definiować, jednak można ją zdefiniować ponownie $stdoutbez błędów / ostrzeżeń (ponowne zdefiniowanie STDOUTspowoduje ostrzeżenie). na przykład możesz:

$stdout = STDERR

To samo dotyczy $stderriSTDERR


Tak więc, aby odpowiedzieć na drugą część pytania, użyj zmiennych globalnych do przekierowania danych wyjściowych, a nie stałych. Po prostu uważaj, aby zmienić to z powrotem w kodzie, ponowne zdefiniowanie zmiennych globalnych może wpłynąć na inne części aplikacji.

Brian
źródło
3
Właściwie, jeśli chcesz przekierować wyjście, prawdopodobnie powinieneś użyć $>domyślnego strumienia wyjściowego, a nie $stdout.
Jörg W Mittag,
10
Właśnie znalazłem komentarz do innego pytania, które mówi $stdouti $>jest aliasami, więc ponowne przypisanie jednego wpłynie na drugie.
jrdioko
9
@jrdioko: Masz rację. Najwyraźniej każdego dnia nie tylko uczę się czegoś nowego, ale też codziennie o czymś zapominam :-)
Jörg W Mittag
2
Czytając więcej, wygląda na to, że lepiej jest użyć IO # reopen zamiast prostego przypisania.
jrdioko
@jrdioko Dlaczego uważasz, że lepiej jest używać IO#reopenw przypadku $stdout? Zupełnie nie zgadzam się z tą opinią. $stdout.reopenMetoda mutuje jego odbiornik, a także wpływają STDOUTjeśli nie przypisane $stdoutwcześniej. Nie mają być synonimami, to nic złego, gdy mają różne wartości z powodu przypisania i otwierając ponownie STDOUTcel, który łamiesz.
skalee
5
  • STDOUT jest stałą globalną, więc nie należy jej zmieniać.
  • $stdout jest predefiniowaną zmienną, więc można ją zmienić.

Jeśli używasz powłoki do przekierowywania:

$ ruby test.rb > test.log

wtedy nie ma znaczenia, który z nich zostanie użyty jako deskryptor pliku dla twojego skryptu, jest określany przed wykonaniem skryptu.

Jeśli jednak próbujesz zmienić deskryptor pliku dla STDOUT systemu operacyjnego z poziomu skryptu Ruby, na przykład, aby wysłać dane wyjściowe do obracającego się zestawu plików dziennika na podstawie bieżącego dnia tygodnia, upewnij się, że używasz $stdout.

shakerlxxv
źródło
5
„STDOUT jest stałą globalną, więc się nie zmieni”. Jest to stała, którą MOŻNA zmienić, ale zostanie wyświetlone ostrzeżenie. STDOUT = $stderr (irb):1: warning: al#=> #<IO:<STDERR>>constant STDOUT >> STDOUT #=> #<IO:<STDERR>>
Tin Man
Ach tak, więc należałoby powiedzieć „więc nie powinno się tego zmieniać”. Dzięki!
shakerlxxv
5

Obie $stdouti STDOUTmają różne znaczenia. Dokumentacja Rubiego jest dość jasna na ten temat:

  • $stdout - Bieżące standardowe wyjście.
  • STDOUT- Standardowe wyjście. Domyślna wartość $ stdout.

Kiedy chcesz pisać na standardowe wyjście, masz na myśli bieżące standardowe wyjście, więc powinieneś pisać do $stdout.

STDOUTnie jest też bezużyteczna. Przechowuje domyślną wartość $stdout. Jeśli kiedykolwiek zmienisz przypisanie $stdout, możesz przywrócić poprzednią wartość za pomocą $stdout = STDOUT.

Ponadto istnieje jeszcze jedna wstępnie zdefiniowana zmienna:

  • $>- Domyślne wyjście dla print, printf, które jest $stdoutdomyślne.

Jednak wygląda na to, że w Rubim 2.3 po prostu zachowuje się jak alias dla $stdout. Ponowne przypisanie $stdoutzmienia wartość $>i odwrotnie.

skalee
źródło