2016-11-15 10 views
2

Я пытаюсь найти способ распечатать индикатор прогресса в командной строке при разборе файлов журнала. Get logfiles => foreach file => foreach line {do}.Печать не работает, пока итерации идут внутри цикла foreach

Идея: я хочу напечатать часть индикатора прогресса в каждом цикле «foreach file». Meaing: распечатайте весь столбец, если вы просто разбираете 1 файл. напечатайте половину строки для каждого файла, когда вы разберете 2 файла и так далее. Вы находите конкретный код внизу.

Проблема: Выход (печать «*») печатается после того, как все операции foreach завершены, а не между ними. Подробности указаны в Кодексе.

Есть ли у кого-нибудь идеи, как печатать внутри foreach? Или может сказать мне проблему? Я не понимаю :(.

my @logfiles=glob($logpath); 

print "<------------------>\n"; 
$vari=20/(scalar @logfiles); 

foreach my $logfile (@logfiles){ 
    open(LOGFILEhandle, $logfile); 
    @lines = <LOGFILEhandle>; 

    print "*" x $vari; #won't work, only after loop. Even a "print "*";" doesn't work 

    foreach my $line (@lines){ 
     #print "*"; works "in between". print "*" x $vari; does not. 

     if ($line=~/xyz/){ 
      ...... 
      ...... 
     } 
    close(LOGFILEhandle); 
    } 
} 
+1

попробуйте 'print '*" x $ vari, "\ n"; 'или установите' $ | = 1'. Возможно, вы [страдали от буферизации] (http://perl.plover.com/FAQs/Buffering.html). – PerlDuck

ответ

3

Вы страдаете от буферизации. Выход в буфере до тех пор, некоторое количество не будет достигнут или напечатать символ новой строки. Для того, чтобы изменить это поведение, просто добавьте

$| = 1 ; 
..

в верхней части файла Это включит AutoFlush для STDOUT Существует более чем один способ сделать это и немного дольше и менее загадочным является Бородины предложение:

STDOUT->autoflush(); 
+2

'STDOUT-> autoflush' гораздо более понятный и может использоваться для любого дескриптора файла. – Borodin

+0

«страдание от буферизации» звучит как общая проблема :). 5 символов заставили его работать. благодаря! – Ocalion

+0

@Borodin Да, вы правы ... Я добавил ваше предложение к ответу. – dgw

3

Я хотел бы предложить модуль Term::ProgressBar, чтобы избежать повторного использования колеса.

#!/usr/bin/perl 
use strict; 
use warnings; 

use Term::ProgressBar; 

my @files = qw (file1 file2 file3 file4); 

my $progress = Term::ProgressBar->new(scalar @files); 

for ([email protected]) { 
    $| = 1; 
    sleep(1); #introducing sleep for demo purpose otherwise bar will fill up quickly 
    #open the file, do some operations and when you are done 
    #update the bar 
    $progress->update($_); 
}