sharon@jpl-devvax.JPL.NASA.GOV (Sharon Hopkins) (02/09/91)
When my alarm went off this morning, it woke me out of a very frustrating dream in which I had this string of characters I was trying to split into an array, only some of the elements kept overlapping. Unfortunately, I only learned subroutines on Monday, and haven't learned split yet, but my subconscious seemed to think I ought to have known how to do it. (I'm told there is at least one Way To Do It, but I haven't had a chance to try it yet.) Do other people dream in perl? :-) I'm pretty sure I know what brought on this particular nightmare, however: I have to get reports out of Sybase now and again, and several of the fields I want are really long, which means I get nasty line wraps, and reports that shouldn't fill one screen take up two or three. All I wanted was a nice, pretty output format. (ISQL lets you select a substring of a particular field, but loses the headers for all the columns you crop that way). So, I asked Larry what I needed to do to squeeze my fields so that I would never get a line of output that was more than 80 characters across. A simple split on white space wouldn't work because several fields that are allocated twenty or thirty characters currently only have a few characters in them. (Example: the field "archiveTime" allows 30 or so characters, but is currently NULL in all the records, which leaves lots of wasted white space). Also, I didn't want to have to specify a different output format for every set of fields I happened to want to select. By about 1:00 (this morning) Larry had come up with the following (which was a lot less readable before he fixed it to work under patchlevel 40, which is as far as the machines I wanted to run on had got): (Note: It's called "squish", and expects a line of column headers, then a line of dashes (with breaks between columns), then the rest of the stuff that belongs in those columns; Larry says it's okay to post it... :-) ----------------------------- --------------- ------------------------------ #!/usr/bin/perl # Get first nonblank line while (<>) { last unless /^\s*$/; } $fieldnames = $_; # Get line with minuses while (<>) { last if /--/; } chop; # make unpack template $template = $_; $template =~ s/-+/"A" . length($&)/eg; $template =~ s/ /x/g; $template =~ s/x+$//; $template =~ s/\d+$/*/; print $template,"\n" if $debugging; $fields = $template =~ tr/A/A/; # count number of fields # make new minuses line to fit in 80 columns $min = $_; $origminuses = $_; $string = '-' x length($min); while (length($min) > 80) { $min =~ s/-$string/$string/ || $string =~ s/-//; } print $min,"\n" if $debugging; $minuses = $min; # make a picture line for format $min =~ tr/-/Q/; $min =~ s/\bQ/@/g; $min =~ tr/Q/</; print $min,"\n" if $debugging; $picture = $min; # Make list of array references for (0..$fields-1) { $fldlist .= "\$F[$_],"; } chop($fldlist); #delete comma # Generate the format at run-time using eval $format = <<"EndOfFormat"; format STDOUT = $picture $fldlist . EndOfFormat print $format if $debugging; eval $format; $_ = $fieldnames; &DOLINE; $_ = $origminuses; &DOLINE; while (<>) { last if /rows affected/; &DOLINE; } sub DOLINE { @F = (); eval '@F = unpack($template, $_)'; write STDOUT; } ----------------------------- ---------------- ----------------------------- Sharon Hopkins sharon@jpl-devvax.Jpl.Nasa.Gov "comp.lang.perl -- Distributed Regression Testing"