Question

Mon programme (qui se trouve être à Perl, bien que je ne pense pas que cette question soit spécifique à Perl) publie des messages d'état à un moment donné du programme du formulaire Progress: x/yyx et yy sont un nombre, comme: Progress: 4/38.

Je voudrais "écraser" la sortie précédente lorsqu'un nouveau message d'état est imprimé afin que je ne remplisse pas l'écran de messages d'état. Jusqu'à présent, j'ai essayé ceci:

my $progressString = "Progress\t$counter / " . $total . "\n";
print $progressString;
#do lots of processing, update $counter
my $i = 0;
while ($i < length($progressString)) {
    print "\b";
    ++$i;
}

Le personnage arrière ne s'imprime pas si j'inclut une nouvelle ligne dans $progressString. Si je laisse de côté la nouvelle ligne, cependant, le tampon de sortie n'est jamais rincé et rien n'imprime.

Quelle est une bonne solution pour cela?

Était-ce utile?

La solution

Utilisez un automatiquement avec STDOUT:

local $| = 1; # Or use IO::Handle; STDOUT->autoflush;

print 'Progress: ';
my $progressString;
while ...
{
  # remove prev progress
  print "\b" x length($progressString) if defined $progressString;
  # do lots of processing, update $counter
  $progressString = "$counter / $total"; # No more newline
  print $progressString; # Will print, because auto-flush is on
  # end of processing
}
print "\n"; # Don't forget the trailing newline

Autres conseils

Dire

$| = 1

Quelque part au début de votre programme pour activer la mise au point automatique pour le tampon de sortie.

Pensez également à utiliser " r" pour remettre le curseur au début de la ligne, plutôt que d'essayer de compter explicitement le nombre d'espaces dont vous avez besoin pour revenir.

Comme vous l'avez dit, n'imprimez pas une nouvelle ligne pendant que votre compteur de progrès est en cours d'exécution, sinon vous imprimerez vos progrès sur une ligne séparée au lieu d'écraser l'ancienne ligne.

Je sais que ce n'est pas tout à fait ce que vous avez demandé, mais peut-être mieux. Je suis arrivé sur ce même problème et donc plutôt que de m'occuper trop de choses. Term::ProgressBar Ce qui a l'air bien aussi.

Vous pouvez également utiliser le Codes d'échappement ANSI Pour contrôler directement le curseur. Ou vous pouvez utiliser Terme :: Readkey faire la même chose.

J'ai dû aborder quelque chose de similaire à cela aujourd'hui. Si cela ne vous dérange pas de réimprimer toute la ligne, vous pourriez faire quelque chose comme ceci:

print "\n";
while (...) {
     print "\rProgress: $counter / $total";
     # do processing work here
     $counter++;
}
print "\n";

Le caractère " r" est un retour chariot - il ramène le curseur au début de la ligne. De cette façon, tout ce que vous imprimez écrase le texte de la notification de progression précédente.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top