Différence entre $ stdout et STDOUT dans Ruby

88

En Ruby, quelle est la différence entre $stdout(précédé d'un signe dollar) et STDOUT(en majuscules)? Lors de la redirection de sortie, laquelle doit être utilisée et pourquoi? Il en va de même pour $stderret STDERR.

Edit: Je viens de trouver une question connexe .

jrdioko
la source
@theTinMan C'est un peu un doublon. Cependant, il faut noter que si les différences entre $stdoutet STDOUTvs $stdinet STDINsont symétriques, les différences entre $stdoutet $>vs $stdinet $<ne le sont pas.
skalee

Réponses:

106

$stdoutest une variable globale qui représente la sortie standard actuelle. STDOUTest une constante représentant la sortie standard et est généralement la valeur par défaut de $stdout.

Étant STDOUTune constante, vous ne devez pas la redéfinir, cependant, vous pouvez la redéfinir $stdoutsans erreurs / avertissements (la redéfinition déclenchera STDOUTun avertissement). par exemple, vous pouvez faire:

$stdout = STDERR

Même chose pour $stderretSTDERR


Donc, pour répondre à l'autre partie de votre question, utilisez les variables globales pour rediriger la sortie, pas les constantes. Veillez simplement à le modifier plus loin dans votre code, la redéfinition des variables globales peut avoir un impact sur d'autres parties de votre application.

Brian
la source
3
En fait, si vous souhaitez rediriger la sortie, vous devriez probablement utiliser $>le flux de sortie par défaut, pas $stdout.
Jörg W Mittag
10
Je viens de trouver un commentaire sur une autre question qui dit $stdoutet $>sont des alias, donc la réaffectation de l'un affectera l'autre.
jrdioko
9
@jrdioko: Vous avez raison. Apparemment, j'apprends non seulement quelque chose de nouveau tous les jours, j'oublie aussi quelque chose tous les jours :-)
Jörg W Mittag
2
Et en lisant plus, il semble qu'il est préférable d'utiliser IO # reopen au lieu d'une simple affectation.
jrdioko
@jrdioko Pourquoi pensez-vous qu'il est préférable d'utiliser IO#reopenen cas de $stdout? Je suis totalement en désaccord avec cette opinion. La $stdout.reopenméthode mute son récepteur et cela affectera également STDOUTsi vous ne l'avez pas réaffecté $stdoutauparavant. Ils ne sont pas censés être des synonymes, il n'y a rien de mal quand ils détiennent des valeurs différentes en raison d'une affectation, et en rouvrant le, STDOUTvous enfreignez son objectif.
skalee
5
  • STDOUT est une constante globale, elle ne doit donc pas être modifiée.
  • $stdout est une variable prédéfinie, elle peut donc être modifiée.

Si vous utilisez le shell pour effectuer la redirection:

$ ruby test.rb > test.log

peu importe alors celui que vous utilisez comme descripteur de fichier pour votre script est déterminé avant que votre script ne soit exécuté.

Cependant, si vous essayez de modifier le descripteur de fichier pour le STDOUT du système d'exploitation à partir de votre script Ruby, par exemple pour envoyer la sortie à un ensemble rotatif de fichiers journaux en fonction du jour actuel de la semaine, vous voudrez vous assurer vous utilisez $stdout.

shakerlxxv
la source
5
"STDOUT est une constante globale, donc ça ne va pas changer". C'est une constante, qui PEUT être modifiée, mais un avertissement sera émis. STDOUT = $stderr (irb):1: warning: al#=> #<IO:<STDERR>>constant STDOUT >> STDOUT #=> #<IO:<STDERR>>
the Tin Man
Ahh oui, donc devrait dire "donc ça ne devrait pas être changé". Merci!
shakerlxxv
5

Les deux $stdoutet STDOUTont des significations différentes. La documentation de Ruby est assez claire sur ce sujet:

  • $stdout - La sortie standard actuelle.
  • STDOUT- La sortie standard. La valeur par défaut de $ stdout.

Lorsque vous voulez écrire sur la sortie standard, vous voulez dire en fait la sortie standard actuelle , vous devez donc écrire dans $stdout.

STDOUTn'est pas inutile aussi. Il stocke la valeur par défaut pour $stdout. Si jamais vous réattribuez $stdout, vous pouvez le restaurer à la valeur précédente avec $stdout = STDOUT.

De plus, il existe une autre variable prédéfinie:

  • $>- La sortie par défaut pour print, printf, qui est $stdoutpar défaut.

Cependant, il ressemble à Ruby 2.3, il se comporte simplement comme un alias pour $stdout. Réaffecter $stdoutmodifie la valeur de $>et vice versa.

skalee
la source