Pergunta

O meu programa (que passa a ser em Perl, embora eu não acho que essa pergunta é Perl-específico) saídas de mensagens de status em um ponto no programa do formulário Progress: x/yy onde x e yy são um número, como: Progress: 4/38.

Eu gostaria de "substituir" a saída anterior quando um novo status de mensagem é impresso para que eu não preencher a tela com mensagens de status.Até então, eu tentei isso:

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

O caractere backspace não imprimir, se eu incluir uma quebra de linha na $progressString.Se eu deixar de fora a quebra de linha, no entanto, o buffer de saída nunca é liberado e nada é impresso.

O que é uma boa solução para isso?

Foi útil?

Solução

Use autoflush com 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

Outras dicas

Dizer

$| = 1

em algum lugar no início do programa para ativar autoflushing para o buffer de saída.

Considere também o uso de " " para mover o cursor para o início da linha, ao invés de tentar explicitamente contar quantos espaços você precisa mover-se para trás.

Como você disse, não imprima uma linha em branco enquanto o contador de progresso está em execução ou outra coisa que você irá imprimir o seu progresso em uma linha separada em vez de substituir a antiga linha.

Eu sei que não é bem o que você pediu, mas possivelmente melhor.Aconteceu esse mesmo problema e assim, em vez de lidar com ele muito fui usando Term::ProgressBar o que parece bom demais.

Você também pode usar o Códigos de escape ANSI para controlar diretamente o cursor.Ou você pode usar Term::ReadKey para fazer a mesma coisa.

Eu tinha que enfrentar algo parecido hoje.Se você não se importa de reimpressão de toda a linha, você poderia fazer algo assim:

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

O " " o caráter é um retorno de carro-- traz novamente o cursor para o início da linha.Dessa forma, qualquer coisa que você imprima substitui a anterior notificação de andamento do texto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top