"I am looking for any suggestions ... that might lead to a more elegant solution."

One of the benefits of using lexical variables is that you can control their scope. Declaring all your variables at the start of runtime, and giving them file-scope, defeats this. You should use the smallest scope possible. You should generally also pass variables to your subroutines: there are exceptions to this such as in the code below; although, do note the anonymous block limiting the scope of the variables not passed in the function call (see also state for an alternative way to handle this).

Using an arrayref, as you've shown, is not something I would do. Using one of the string formatting functions (sprintf in the code below) would be a better choice. Adding a newline to each line of output, actually creates something more like a log than a progress indicator. Starting each output line with a carriage return (\r) is not doing what I think you hoped it would; the usual way to handle this is to use backspaces (\b) and then write the new indicator lines, effectively overwriting the previous indicator line.

Also note that writing lines without a terminal newline can cause buffering problems. I've set the special variable "$|" to overcome this; and localised that change so that it doesn't affect other I/O.

Here's example code implementing those techniques.

#!/usr/bin/env perl use strict; use warnings; my @files = map { "file_$_" } 5 .. 14; for (0 .. $#files) { show_progress(\@files, $_); # Process $files->[$_] here. For testing: sleep 1; } show_done(); { my ($prog_fmt, $last_msg_len); BEGIN { $prog_fmt = 'Processing "%s" (%d of %d) ...'; $last_msg_len = 0; } sub show_progress { my ($files, $index) = @_; local $| = 1; my $clear = "\b" x $last_msg_len; my $msg = sprintf $prog_fmt, $files->[$index], 1+$index, 0+@$f +iles; $last_msg_len = length $msg; print $clear, $msg; return; } } sub show_done { print "\nProcessing completed.\n"; return; }

The first line of output looks like this:

Processing "file_5" (1 of 10) ...

That line is continually overwritten. The final output looks like this:

Processing "file_14" (10 of 10) ... Processing completed.

— Ken


In reply to Re: Printing to stdout an array of strings and scalar references by kcott
in thread Printing to stdout an array of strings and scalar references by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.