G'day Jake,

Welcome to the monastery.

I see ++Athanasius has provided you with an answer to your question.

Whenever you see almost identical lines of code being repeated, such as you have here, consider abstracting that into a subroutine.

Apart from the physical effort of typing in all that code, you're having to do calculations at every step to determine each substring's offset.

Your computer can perform calculations faster and more accurately than you can: tell it to do this work. :-)

Any errors you make are likely to propogate to each successive line: a simple off-by-one error due to calculating the first character as being at postion 1 instead of position 0 would mean having to recalculate all but the first of your substr statements. Actually, it looks like that's exactly what you've done! [substr($line, 0, 135) addresses positions 0 to 134: what happened to substr($line, 135, 1)?]

Beyond the fact that hand-coding all of this is laborious, error-prone and may take several attempts to get it right, think of the maintenance issues. You have 6 characters assigned for your dates (11 chars for "DATE=${mdy}" and 6 chars for "${mdy}"): that looks like a MMDDYY format. What if you decided to make this more robust and avoid the so-called Y2K Bug by using a MMDDYYYY format: more calculations, more code modifications, and more potential errors.

The only information you should really need to concern yourself with is the size of the fields and the data to go into those fields. Let the computer worry about substring offsets, data size and whether padding is required.

Here's a simplified example of how you might go about this. Consider adding validation code, e.g. to check that you're not trying to put data into a field that's too small to hold it.

#!/usr/bin/env perl -l use strict; use warnings; my ($mdy, $hms, $CLIENT_ID) = qw{MMDDYY HHMMSS 123}; my @fields = ( [135, ''], [11, "DATE=$mdy"], [6, $mdy], [6, $hms], [3, ''], [17, ''], [8, 'G1ADP'], [3, $CLIENT_ID], ); my $line = pack 'A510'; my $offset = 0; add_field(\$line, \$offset, @$_) for @fields; print 'Length of line = ', length $line; print "Line = |$line|"; sub add_field { my ($line_ref, $offset_ref, $length, $data) = @_; substr($$line_ref, $$offset_ref, $length) = $data . ' ' x ($length - length $data); $$offset_ref += $length; }

Output:

Length of line = 510 Line = | + + DATE=MMDDYYMMDDYYHHMMSS G1ADP 123 + + + + + |

-- Ken


In reply to Re: Google has failed me! Using pack and substr for fixed width file output by kcott
in thread Google has failed me! Using pack and substr for fixed width file output by spudulike

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.