in reply to Re: format characters
in thread format characters

I am trying what you suggested (and thank you!) but its not working. I want to replace this code:
<snipped the _TOP> format STDOUT = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<< @<<<<<<< @<<<<<<<<<<<<< <<<<<<<<<< @||||||||||||||||||| @##.## $sfile, + $user, $grp, $gcos, dateme($mod,$mod2), $sz ~~ .

with this code

my $format = "format STDOUT = \n" . '@' . '<' x 125 . $sfile . q{ } . '@' . '<' x 8 . $user . q{ } . '@' . '<' x 8 . $grp . q{ } . '@' . '<' x 25 . $gcos . q{ } . '@' . '|' x 20 . dateme($mod,$mod2) . q{ } . '@' . '#' x 2 . '.##' . $sz . "\n" . "~~\n" . ".\n" ;

And the errors I am getting are:

Use of uninitialized value in concatenation (.) or string at find_hog. +tdy line 49. Use of uninitialized value in concatenation (.) or string at find_hog. +tdy line 49. Use of uninitialized value in concatenation (.) or string at find_hog. +tdy line 49. Use of uninitialized value in concatenation (.) or string at find_hog. +tdy line 49. Use of uninitialized value in localtime at find_hog.tdy line 105. Use of uninitialized value in concatenation (.) or string at find_hog. +tdy line 49. format STDOUT = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< +<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @<<<<<<<< +@<<<<<<<< @<<<<<<<<<<<<<<<<<<<<<<<<< @||||||||||||||||||||19:00:00- +12/31/69 @##.## ~~ . Undefined format "STDOUT" called at find_hog.tdy line 227.

Do I use a regular write? I am confused on how write knows about $format?

Replies are listed 'Best First'.
Re^3: format characters
by shmem (Chancellor) on Feb 10, 2008 at 20:43 UTC
    I am trying what you suggested (and thank you!) but its not working.

    Huh? I didn't suggest that - I wrote about an editor (vi) command. But since you are bringing that up - re-read perlform, the chapter "Accessing Formatting Internals".

    If you construct your format into a string, you have to either eval it -

    my $format = '| @' . '>' x 10 . ' | ' . '@' . '<' x 10 . " |\n" . '$given, $surname' ."\n" . '.'; eval "format STDOUT = \n$format"; for ([qw(Bill Bruford)],[qw(Ginger Baker)]) { ($given, $surname) = @$_; write; } __END__ | Bill | Bruford | | Ginger | Baker |

    or use formline and the accumulator $^A :

    my $format = '| @' . '>' x 10 . ' | ' . '@' . '<' x 10 . " |\n"; for ([qw(Bill Bruford)],[qw(Ginger Baker)]) { formline( $format,@$_); print $^A; $^A = ''; } __END__ | Bill | Bruford | | Ginger | Baker |

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      OK thank you much! I understand. So now I am asking

      1) Not sure why I am seeing 'Filename' and 'Owner' when print $^A is invoked. Can you see why?

      2) Is there a better way to line up my headings with the data then what I am doing? For example, q{ } x ##

      __OUTPUT__ REPORT OF .... on host: sparky Filename PageOwner 0 <snip> __END_OUTPUT__ my $fn = q<Filename> ; my $owr = q<Owner> ; my $go = q<GroupOwner> ; my $gc = q<Gecos> ; my $lmd = q<LastModifiedDate> ; my $smb = q<Size Mb> ; my $format_TOP = 'REPORT OF LARGE FILES on:' . "\n" . qx(hostname) . '@' . '<' x 12 . "\n\n\n" . 'Page' . '@' . '<' x 4 . "\n" . $% . "\n" . $fn . q{ } x 10 . $owr . q{ } x 6 . $go . q{ } x 1 . $gc . q{ } x 25 . $lmd . q{ } x 6 . $smb . "\n" . '=' x 8 . q{ } x 10 . '=' x 5 . q{ } x 6 . '=' x 10 . q{ } x 1 . '=' x 5 . q{ } x 25 . '=' x 16 . q{ } x 6 . '=' x 7 . "\n" ; formline( $format_TOP, $fn, $owr, $go, $gc, $lmd, $smb ) ; print $^A ; $^A = q{}; <snip>
        A picture string for formline is different from a declared format. You don't put the variables under the picture line, instead you pass them in as arguments to formline().
        1) How can I get $% to work using formline. The page number is not showing up.

        That's because you are storing the value of $% in the picture string.

        Use a placeholder, e.g @##, and pass $% as a parameter into formline() at the appropriate position.

        2) Not sure why I am seeing 'Filename' and 'Owner' when print $^A is invoked. Can you see why?

        Because you are constructing the formline picture string with the contents of $fn and $owr ? After setting up that string, $fn and $owr have no relation to the format string whatsover, and it doesn't make sense to pass them into formline() if the format string contains no placeholder for them.

        3) Is there a better way to line up my headings with the data then what I am doing? For example, q{ } x ##

        The construct q{ } x ## will trigger a syntax error if it appears in code, since there's no right hand side for the x operator, because ## is a comment.

        If used within a format picture string, q{ } x ## will show up literally, since there's no way to include parts to be eval'ed in a format picture, and the ## doesn't have a leading @.

        For what you want to do, evalling the constructed format picture is the best way IMHO. Mind you, not all uses of eval are evil. For instance, eval is what is done executing a use statement.

        If was constructing formats on the fly, I'd probably do something like this:

        my @formvars = ( # header fieldlen type [ 'Filename', 17, 'l' ], [ 'Owner', 10, 'l' ], [ 'GroupOwner', 10, 'l' ], [ 'Gecos', 29, 'l' ], [ 'LastModifiedDate', 21, 'l' ], [ 'Size Mb', 7, 'n' ], ); my %f = ( l => '<', r => '>', n => '#' ); my $hostname = qx(hostname); my $format_TOP = join ("\n", 'format STDOUT_TOP =', 'REPORT OF LARGE FILES on:', '@' . '<' x 12, '$hostname', '', 'Page @<<<<', '$%', join(' ', map { sprintf "%-$_->[1]s", $_->[0] } @formvars), join(' ', map { sprintf "%-$_->[1]s", '=' x length($_->[0]) } @for +mvars), '.' ); my $format_STDOUT = join("\n", 'format STDOUT =', join(' ', map { '@' . $f{$_->[2]} x ($_->[1] - 1) } @formvars), join(', ', map { "\$_[$_]" } 0..$#formvars), '.' ); eval $format_TOP; eval $format_STDOUT; opendir(D,'.'); my @files = grep(!/^\.\.?$/,readdir D); for(@files) { my @s = stat; if ($s[7] > 2**20) { # 1 MB my ($nm,$gc) = (getpwuid $s[4])[0,6]; my $group = (getgrgid $s[5])[0]; my $lmd = scalar localtime $s[9]; my $size = int ($s[7]/2**20); @_ = ( $_, $nm, $group, $gc, $lmd, $size ); write; } }; __END__

        That way you can adjust the column widths by just changing numbers.

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}