in reply to misalined TABs using substr,LAST_MATCH_START/END,regex

Just for fun, I present code for a different, but related problem.
Usually the idea is to compress as many columns onto the page as possible. This means removing tabs instead of adding them except when necessary for column alignment and allowing for a least one blank space between columns.

My code using tabs within code tags doesn't render exactly right on Perl Monks and I don't know why.

use strict; use warnings; print "123456789\n"; print "\t1\n"; __END__ 123456789 1
The "1" should be underneath the 9, but with my browser it is not.

Be that presentation problem be as it may, this code adjusts the tabs correctly for the given input, at least as viewed with my program editor. I think I handled the "off by one" situation correctly, mileage varies.

use strict; use warnings; use Data::Dump qw(dump dd); $|=1; my $input2 = << "EOF"; foo bar baz booz qaaz abc foo bar baz booz qaaz abc 123 foo bar thisis15chars15 booz qaaz abc EOF use constant {TAB_SPACES =>8}; # normal default is 8 ####### # Table 2 is more complex - reduce tabs when possible, # add tabs when needed. # # As each line is read, the maximum required width of each column # is calculated. # # Table is stored in @table2 without separators. # # Reformatted table is output assuming TAB_SPACES # open my $input2_fh, "<", \$input2 or die "$!"; print "********\nTable2 input in raw form:\n********\n"; my @table2; my @max_chars; while (<$input2_fh>) { print; chomp; my $i=0; my @tokens; foreach my $field (@tokens = split /\t+/,$_) { $max_chars[$i] //= 0; $max_chars[$i] = length $field if (length $field > $max_chars[ +$i]); $i++; } push (@table2,[@tokens]); } print "\nData dump of Table2:\n"; dd \@table2; print "\n******\nReformatted Table:\n*****\n"; foreach my $row_ref (@table2) { my $i = 0; my @line = @$row_ref; while (defined (my $field = shift @line)) { my $alignment_spaces = $max_chars[$i]-length($field); my $n_tabs = int($alignment_spaces/TAB_SPACES)+1; print "".$field, (@line) ? "\t" x $n_tabs : "\n"; $i++; } } __END__ ******** Table2 input in raw form: ******** foo bar baz booz qaaz abc foo bar baz booz qaaz abc 123 foo bar thisis15chars15 booz qaaz abc Data dump of Table2: [ ["foo", "bar", "baz", "booz", "qaaz", "abc"], ["foo", "bar", "baz", "booz", "qaaz", "abc", 123], ["foo", "bar", "thisis15chars15", "booz", "qaaz", "abc"], ] ****** Reformatted Table: ***** foo bar baz booz qaaz abc foo bar baz booz qaaz abc 123 foo bar thisis15chars15 booz qaaz abc
When run on my computer, all of the "booz" column lines up.