harishnuti has asked for the wisdom of the Perl Monks concerning the following question:


Hello Monks i have a problem in printing arrays ( containing elements) in fixed column width.
* i have one array containing header's or column names
* The next array containing multiple rows i.e. data
* i want to display in report format with each header with fixed width and corresponding data should come below header..
pls see below data to get an idea
__DATA__ TABNAME 06100 01010 06000 00110A # The above is header which is present in @header !W31801!-->!919!-->!90200809!-->!840!-->!MO! !W31801!-->!919!-->!902008!-->!74!-->!MO! #The above are the data present in @data array # iam doing below ... my $disp = sprintf("-%10s\n",join("\t",@header)); print $disp; # i printed header foreach my $line (@data){ my @arr = split(/-->/,$line); my $disp = sprintf("-%10s\n",join("\t",@arr)); print $disp; } # From above iam cant achieve what i need, the resultant data is out o +f format... # All i need is , no matter whats the size of data or header, i want t +o print each column with width of 10 characters . __DATA__ -TABNAME 06100 01010 06000 00110A -!W31801! !919! !90200809! !840! !MO! -!W31801! !919! !902008! !74! !MO! # As you can see output , headers are not alighned properly, i need he +aders and corresponding data to be left alighned and in same column..

Replies are listed 'Best First'.
Re: Print Array items in Fixed width
by BrowserUk (Patriarch) on Jul 31, 2008 at 05:46 UTC

    Formatting fixed width output is often easier with pack:

    #! perl -slw use strict; print pack '(A10)*', split ' ', <DATA>; while( <DATA> ) { chomp; print pack '(A10)*', split '-->', $_; } __DATA__ TABNAME 06100 01010 06000 00110A !W31801!-->!919!-->!90200809!-->!840!-->!MO! !W31801!-->!919!-->!902008!-->!74!-->!MO!
    <>Gives
    c:\test>junk4 TABNAME 06100 01010 06000 00110A !W31801! !919! !90200809!!840! !MO! !W31801! !919! !902008! !74! !MO!

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Print Array items in Fixed width
by ikegami (Patriarch) on Jul 31, 2008 at 04:31 UTC

    "%10s" is used to format "!W31801!\t!919!\t!90200809!\t!840!\t!MO!", more than 10 characters, so you might as well have used "%s". You need to apply "%10s" (actually "%-10s" if you want to left-justify) to every field of every line, not just every line.

    print('-', (map { sprintf('%-10s', $_) } @header), "\n"); foreach my $line (@data) { my @fields = split(/-->/, $line); print('-', (map { sprintf('%-10s', $_) } @fields), "\n"); }
    or
    my $format = '-' . ('%-10s' x @header) . "\n"; printf($format, @header); foreach my $line (@data) { printf($format, split(/-->/, $line)); }

      yes ikegami, this is what iam looking for, i tried several alternatives and spent quiet a lot of time, Wow thanks a lot for looking into my problem and it was a good info and learning for me...once again thanks a lot..
Re: Print Array items in Fixed width
by broomduster (Priest) on Jul 31, 2008 at 08:53 UTC
    And there's always format(perlform)... Modifying ikegami's first example slightly:

    my @header = qw( TABNAME 06100 01010 06000 00110A ); my @data = qw( !W31801!-->!919!-->!90200809!-->!840!-->!MO! !W31801!-->!919!-->!902008!-->!74!-->!MO! ); my @fields; #declare here so it's visible to format below foreach my $line (@data) { @fields = split(/-->/, $line); write; } format STDOUT_TOP = @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< @header . format STDOUT = @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< @<<<<<<<<< @fields .

      yes perl formats i have tried in some of my applications, but here iam not sure how many columns my data has, the above i showed is only a fragment of my whole file, i.e. W31801 is one table with 5 headers, some other tables will have 10 or more, so i needed variable length formatting ..

      Thanks for pack functions, indeed very informative and i will note it and will implement in other requirements.

        The only real downside of pack compared with sprintf, is that pack always left justifies the fields where sprintf can do right justification also.

        If you need all the fields right justified, there is a simple trick involving 3 reverses:

        @data = qw[ the quick brown fox jumps the lazy dog ];; print pack '(A10)*', @data;; the quick brown fox jumps the lazy +dog print scalar reverse pack '(A10)*', map scalar reverse, reverse @data; +; the quick brown fox jumps the lazy + dog

        Doesn't help for mixed justification though.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        ... W31801 is one table with 5 headers, some other tables will have 10 or more, so i needed variable length formatting
        If you have "variable fixed widths", and a variable number of columns, then perlform is not the answer. But that wasn't the question you asked, either.