Diferença entre $ stdout e STDOUT em Ruby

88

Em Ruby, qual é a diferença entre $stdout(precedido por um cifrão) e STDOUT(em maiúsculas)? Ao fazer o redirecionamento de saída, o que deve ser usado e por quê? O mesmo vale para $stderre STDERR.

Edit: Acabei de encontrar uma questão relacionada .

Jrdioko
fonte
possível duplicata de Qual é a diferença entre STDIN e $ stdin em Ruby?
o Homem de Lata de
@theTinMan De certa forma, é uma duplicata. No entanto, deve-se notar que, enquanto as diferenças entre $stdoute STDOUTvs $stdine STDINsão simétricas, as diferenças entre $stdoute $>vs $stdine $<não são.
skalee

Respostas:

105

$stdouté uma variável global que representa a saída padrão atual. STDOUTé uma constante que representa a saída padrão e normalmente é o valor padrão de $stdout.

Por STDOUTser uma constante, você não deve redefini-la, no entanto, você pode redefinir $stdoutsem erros / avisos (redefinir STDOUTgerará um aviso). por exemplo, você pode fazer:

$stdout = STDERR

O mesmo vale para $stderreSTDERR


Portanto, para responder à outra parte da sua pergunta, use as variáveis ​​globais para redirecionar a saída, não as constantes. Apenas tome cuidado para alterá-lo mais adiante em seu código, a redefinição de variáveis ​​globais pode afetar outras partes de seu aplicativo.

Brian
fonte
3
Na verdade, se você deseja redirecionar a saída, provavelmente deve usar $>o fluxo de saída padrão, não $stdout.
Jörg W Mittag
9
Acabei de encontrar um comentário em outra pergunta que diz $stdoute $>são aliases, portanto, reatribuir um afetará o outro.
Jrdioko
9
@jrdioko: Você está certo. Aparentemente, eu não apenas aprendo algo novo todos os dias, mas também esqueço algo todos os dias :-)
Jörg W Mittag
2
E lendo mais, parece que é melhor usar IO # reopen em vez de atribuição simples.
Jrdioko
@jrdioko Por que você acha que é melhor usar IO#reopenno caso de $stdout? Eu discordo totalmente dessa opinião. O $stdout.reopenmétodo muda seu receptor e isso também afetará STDOUTse você não tiver reatribuído $stdoutantes. Eles não devem ser sinônimos, não é nada ruim quando eles mantêm valores diferentes devido à atribuição e, ao reabrir o, STDOUTvocê está quebrando seu propósito.
skalee
5
  • STDOUT é uma constante global, portanto, não deve ser alterada.
  • $stdout é uma variável predefinida, portanto, pode ser alterada.

Se você estiver usando o shell para fazer o redirecionamento:

$ ruby test.rb > test.log

então, não importa qual você usa como descritor de arquivo para seu script, está sendo determinado antes de seu script ser executado.

No entanto, se você estiver tentando alterar o descritor de arquivo do STDOUT do sistema operacional de dentro do seu script Ruby, por exemplo, para enviar a saída para um conjunto rotativo de arquivos de log com base no dia atual da semana, então você vai querer ter certeza você usa $stdout.

shakerlxxv
fonte
5
“STDOUT é uma constante global, então não vai mudar”. É uma constante que PODE ser alterada, mas será emitido um aviso. STDOUT = $stderr (irb):1: warning: al#=> #<IO:<STDERR>>constant STDOUT >> STDOUT #=> #<IO:<STDERR>>
The Tin Man
Ahh sim, então deve dizer "então não deve ser alterado". Obrigado!
shakerlxxv
5

Ambos $stdoute STDOUTtêm significados diferentes. A documentação do Ruby é bastante clara neste tópico:

  • $stdout - A saída padrão atual.
  • STDOUT- A saída padrão. O valor padrão para $ stdout.

Quando você quer escrever para a saída padrão, então você realmente quer dizer a saída padrão atual , portanto, você deve escrever para$stdout .

STDOUTnão é inútil também. Ele armazena o valor padrão para $stdout. Se você alguma vez reatribuir $stdout, poderá restaurá-lo para o valor anterior com $stdout = STDOUT.

Além disso, há mais uma variável predefinida:

  • $>- A saída padrão para print, printf, que é o $stdoutpadrão.

No entanto, parece que no Ruby 2.3, ele simplesmente se comporta como um alias para $stdout. Reatribuir $stdoutaltera o valor de $>e vice-versa.

Skalee
fonte