in reply to Google has failed me! Using pack and substr for fixed width file output

spudulike:

Following your pattern, substr($line,190,507) looks like it should be substr($line,190,317).

For what it's worth, I deal with flat files quite a bit. Generally, though, I use pack and unpack instead of substr. That way, I can use the same format string for both packing and unpacking, kinda like this:

my $packfmt = "A135A11A6A6A20A8A3A978"; my $outline = pack $packfmt, " ", "DATE=${mdy}", ${mdy}, ${hms}, " ", "G1ADP", $CLIENT_ID, " "; # Unpack, trailing blanks preserved (undef, $DMDY, $mdy, $hms, undef, $CLIENT_ID) = unpack $packfmt, $outline; # Unpack 1: remove trailing blanks (same format, but # using map to trim the strings): (undef, $DMDY, $mdy, $hms, undef, $CLIENT_ID) = map { s/\s+$//; $_ } unpack $packfmt, $outline; # Unpack 2: remove trailing blanks, different format my $parsefmt = lc($packfmt); (undef, $DMDY, $mdy, $hms, undef, $CLIENT_ID) = unpack $parsefmt, $outline;

Note: I don't have perl on my work machine, so this is (a) from memory, and (b) quite possibly a bit broken.

...roboticus

When your only tool is a hammer, all problems look like your thumb.

Replies are listed 'Best First'.
Re^2: Google has failed me! Using pack and substr for fixed width file output
by Anonymous Monk on Apr 08, 2014 at 20:32 UTC
Re^2: Google has failed me! Using pack and substr for fixed width file output
by spudulike (Novice) on Apr 09, 2014 at 06:15 UTC

    Hi Roboticus,

    It's good to know that there are other fixed width hackers out there :-)

    I did use pack for a while and I did find it easier and faster to create a solution using it. But I had a problem explaining how to match up the fields with the pack format to the supporting teams. They couldn't seem to get their heads around it. So, for me, I got called less if I developed the solution using substr coz (I suppose) it was easier for the support bods to conceptualise the approach.

    Thanks though, it's nice to know I'm <drum roll please> part of the <ahem> pack. Thank you very much, I'm here til Thursday - try the fish.

    Cheers, Jake

      There are all kinds of interesting games you can play with pack, and it should be easy to encapsulate your solution in a function (with lotsa validation) so that maintainers only see data. See below.

      Note that the  @ pack template specifier fills with nulls, so if you want space-filling, you need the
          $packed =~ tr{\000}{ };
      statement. Note also that  @ is absolute, so maybe play around and see, e.g., what happens if the  date offset is set to 1 or 2.

      c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "use constant ORDER => qw(date client_id info); ;; my %o_l = ( date => { qw(off 0 len 6 field 040814) }, client_id => { qw(off 6 len 8 field WayTooMuchClientID) }, info => { qw(off 20 len 7 field G1APD) }, ); ;; my $fields = join ' ', map qq{\@$o_l{$_}{off} A$o_l{$_}{len}}, map { exists $o_l{$_} or die qq{bad '$_'}; $_; } ORDER ; ;; my $packed = pack $fields, map $o_l{$_}{field}, ORDER; $packed =~ tr{\000}{ }; print 'packed len ', length $packed, qq{ '$packed'}; ;; my $total = 30; die 'truncation!' if length($packed) > $total; my $line = pack qq{A$total}, $packed; print 'total len ', length($line), qq{ '$line'}; ;; dd \$line; " packed len 27 '040814WayTooMu G1APD ' total len 30 '040814WayTooMu G1APD ' \"040814WayTooMu G1APD "