On Wed, Jun 20, 2001 at 11:41:29PM +0100, Mark Bedish wrote:
> I am using substrings in a screipt and wondered if there was a better
> perlish way to do it. I am taking data from a mainframe system and
> reformatting it but the substring seems to be quite slow, like visual
> basic, the original.
>
> Any pointers on a better method would be much appreciated.
I can't really give any pointers on a better method because I don't know
enough about what you're doing in order to generalize things. However,
substr shouldn't, by any means, be slow, unless you're doing a lot of
operations, in which case anything you do is likely to be slow.
However, there are some optimizations, both speed and readability-wise, that
can be done with your code examples.
> my @fields = unpack($template, $_);
What is $template, anyhow?
> # add zoned decimals - overpunch requires translation
> for $i (8,9,10,12) {
This seems very odd. Perhaps you should just unpack what you need, using
the "@" template.
> if (unpack(c1,(substr($fields[$i],-1))) > 57)
> {
>
> substr($fields[$i],-1) =~ tr/}JKLMNOPQR/0123456789/;
> $fields[$i] = '-' . substr($fields[$i],1,12);
> }
>
> # add decimal, point
> $fields[$i] = substr($fields[$i],0,11) . '.' .
> substr($fields[$i],-2);
> }
Probably better written as:
foreach my $field (@fields[8, 9, 10, 12]) {
if (ord(substr($field, -1)) > 57) {
substr($field, -1) =~ tr/}JKLMNOPQR/0123456789/;
substr($field, 0, 1) = "-";
}
# add decimal point
substr($field, 11, 0) = ".";
}
I hope I've got the gist of it, but even if not, you can adapt the ideas.
I'm assuming each of your fields is a 13-character string you're turning
into a number. Regarding the decimal, you could also divide by 100, though
you may run into floating point overflows.
> # find bad character and replace with a space or whatever
> my @testbad = unpack(c65,$fields[7]);
>
> print LOG "Unpacked format for array: \n";
>
> for $i (0..64) { print LOG $testbad[$i]; }
print LOG join("", @testbad);
This is assuming you're not running with -l.
> print LOG "\n";
>
> for $i (0..64) {
>
> if ($testbad[$i] == 13) { $testbad[$i] = 40; }
>
>
> }
foreach my $bad (@testbad) {
if ($bad == 13) { $bad = 40 }
}
or, better yet, replace the unpack and this loop with:
$fields[7] =~ tr/\x0D/\x20/;
You'll notice here, and above in the fields processing, I'm using the
aliasing feature of foreach. $bad (and above, $field) are aliases of each
element of the array, so modifications carry through.
I have no idea if this'll help you, but there you go.
Michael
--
Administrator www.shoebox.net
Programmer, System Administrator www.gallanttech.com
--