Pregunta

Mi programa (que resulta que está en Perl, aunque no creo que esta pregunta sea específica de Perl) genera mensajes de estado en un punto del programa del formulario Progress: x/yy dónde x y yy son un número, como: Progress: 4/38.

Me gustaría "sobrescribir" el resultado anterior cuando se imprime un nuevo mensaje de estado para no llenar la pantalla con mensajes de estado.Hasta ahora he probado esto:

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;
}

El carácter de retroceso no se imprimirá si incluyo una nueva línea en $progressString.Sin embargo, si omito la nueva línea, el búfer de salida nunca se vacía y no se imprime nada.

¿Cuál es una buena solución para esto?

¿Fue útil?

Solución

Utilice descarga automática con 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

Otros consejos

Decir

$| = 1

en algún lugar temprano de su programa para activar el vaciado automático del búfer de salida.

También considere usar " " para mover el cursor de regreso al principio de la línea, en lugar de intentar contar explícitamente cuántos espacios necesita retroceder.

Como dijiste, no imprimas una nueva línea mientras el contador de progreso esté funcionando o imprimirás tu progreso en una línea separada en lugar de sobrescribir la línea anterior.

Sé que no es exactamente lo que pediste, pero posiblemente sea mejor.Me encontré con el mismo problema y, en lugar de solucionarlo demasiado, comencé a usar Term::ProgressBar que también se ve bien.

También puedes utilizar el Códigos de escape ANSI para controlar directamente el cursor.O puedes usar Término::LeerClave para hacer lo mismo.

Tuve que abordar algo similar a esto hoy.Si no le importa reimprimir la línea completa, puede hacer algo como esto:

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

El carácter " " es un retorno de carro: devuelve el cursor al principio de la línea.De esa manera, todo lo que imprima sobrescribirá el texto de la notificación de progreso anterior.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top