frech@mwraaa.army.mil (Norman R. Frech CPLS) (06/06/90)
Greetings,
I am fairly new to perl and the following is a program which I
developed to read a file off an ibm and convert the packed values
to something usable. It then writes the data down in delimited form
for dbaseiii. The program seems to work but I have a feeling
it is a terrible hack and would appreciate some kind criticism
or possible improvements, etc.
Thanks, Norm Frech <frech@mwraaa.army.mil>
*** cut here ***
@lookup[0] = ('{}0');
@lookup[1] = ('AJ1');
@lookup[2] = ('BK2');
@lookup[3] = ('CL3');
@lookup[4] = ('DM4');
@lookup[5] = ('EN5');
@lookup[6] = ('FO6');
@lookup[7] = ('GP7');
@lookup[8] = ('HQ8');
@lookup[9] = ('IR9');
while (<>) {
chop;
$field1 = substr($_,0,5);
$field2 = substr($_,5,13);
$field3 = substr($_,18,4);
$field4 = substr($_,22,40);
$field5 = substr($_,62,1);
$field6 = substr($_,63,1);
$field7 = substr($_,64,3);
$onhand = substr($_,67,9);
$stock_val = substr($_,76,9);
$field8 = substr($_,85,9);
$field9 = substr($_,94,1);
$field10 = substr($_,95,5);
# ship two values to be whack
$onhand = &packibm($onhand);
$stock_val = &packibm($stock_val);
# print the values
print "\"",$field1,"\"\,\"",$field2,"\"\,\"",$field3,"\"\,\"";
print $field4,"\"\,\"",$field5,"\"\,\"",$field6,"\"\,\"",$field7;
print "\"\,",$onhand,"\,",$stock_val,"\,",$field8;
print "\,\"",$field9,"\"\,\"",$field10,"\"\n";
}
sub packibm {
local($value) = @_;
$len = length($value);
$tend = substr($value,0,$len - 1);
$lval = substr($value,$len - 1,1);
$get = &calval($lval);
if ($i < 10) {
return($tend * 10 + $i);
}
else
{
return($tend * 10 * -1 + (($i - 10) * -1));
}
}
sub calval {
for ($i = 0; $i < 10; $i++) {
for ($j = 0; $j < 3; $j++) {
$look = substr(@lookup[$i],$j,1);
if ($lval =~ $look) {
if ($j == 1) {
$i = $i + 10;
}
return $i;
}
}
}
}
*** cut here ***merlyn@iwarp.intel.com (Randal Schwartz) (06/06/90)
In article <1990Jun6.004442.14479@uvaarpa.Virginia.EDU>, frech@mwraaa (Norman R. Frech CPLS) writes: | Greetings, | | I am fairly new to perl and the following is a program which I | developed to read a file off an ibm and convert the packed values | to something usable. It then writes the data down in delimited form | for dbaseiii. The program seems to work but I have a feeling | it is a terrible hack and would appreciate some kind criticism | or possible improvements, etc. Here's what I could do in 15 minutes. Might be a few typos. Caveat Executor. I tried to keep your logic and order (had to, with that time limit), but part of the work is learning to "Think Perl". ################################################## cut here @lookup = split(/ /,'{}0 AJ1 BK2 CL3 DM4 EN5 FO6 GP7 HQ8 IR9'); while (<>) { chop; ($f1,$f2,$f3,$f4,$f5,$f6,$f7,$onhand,$stock_val,$f8,$f9,$f10) = /^(.{5})(.{13})(....)(.{40})(.)(.)(...)(.{9})(.{9})(.)(.{5})/; # ship two values to be whack $onhand = &packibm($onhand); $stock_val = &packibm($stock_val); # print the values print '"', join('","', $f1, $f2, $f3, $f4, $f5, $f6, $f7, $onhand, $stock_val, $f8, $f9, $f10), '"', "\n"; } sub packibm { local($_) = @_; local($tend,$lval) = /(.*)(.)/; local($get) = &calval($lval); if ($get < 10) { ## meant $get instead of $i, I hope return($tend * 10 + $get); ## ditto } else { return($tend * 10 * -1 + (($get - 10) * -1)); ## ditto } } ## there is something very non-perlish about the following code, but ## I couldn't reverse engineer it in the few minutes I had to do this. ## Larry? sub calval { local($i,$j); for ($i = 0; $i < 10; $i++) { for ($j = 0; $j < 3; $j++) { $look = substr(@lookup[$i],$j,1); if ($lval =~ $look) { if ($j == 1) { $i = $i + 10; } return $i; } } } } ################################################## cut here print substr("Of course, I'm Just another Perl hacker,",-25,25); -- /=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\ | on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III | | merlyn@iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn | \=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/
lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (06/07/90)
In article <1990Jun6.022140.13168@iwarp.intel.com> merlyn@iwarp.intel.com (Randal Schwartz) writes: : In article <1990Jun6.004442.14479@uvaarpa.Virginia.EDU>, frech@mwraaa (Norman R. Frech CPLS) writes: : | Greetings, : | : | I am fairly new to perl and the following is a program which I : | developed to read a file off an ibm and convert the packed values : | to something usable. It then writes the data down in delimited form : | for dbaseiii. The program seems to work but I have a feeling : | it is a terrible hack and would appreciate some kind criticism : | or possible improvements, etc. : : Here's what I could do in 15 minutes. Might be a few typos. Caveat : Executor. : : I tried to keep your logic and order (had to, with that time limit), : but part of the work is learning to "Think Perl". : : ################################################## cut here : @lookup = split(/ /,'{}0 AJ1 BK2 CL3 DM4 EN5 FO6 GP7 HQ8 IR9'); @code{ '{', 'A' .. 'I', '}', 'J' .. 'R', '0' .. '9' } = (0 .. 19, 0 .. 9); or for (split(//, "{ABCDEFGHI}JKLMNOPQR0123456789")) { $code{$_} = $cnt++ % 20; } or even %code = ( '{', 0, '}', 10, '0', 0, 'A', 1, 'J', 11, '1', 1, 'B', 2, 'K', 12, '2', 2, 'C', 3, 'L', 13, '3', 3, 'D', 4, 'M', 14, '4', 4, 'E', 5, 'N', 15, '5', 5, 'F', 6, 'O', 16, '6', 6, 'G', 7, 'P', 17, '7', 7, 'H', 8, 'Q', 18, '8', 8, 'I', 9, 'R', 19, '9', 9, }; : while (<>) { : chop; : ($f1,$f2,$f3,$f4,$f5,$f6,$f7,$onhand,$stock_val,$f8,$f9,$f10) = : /^(.{5})(.{13})(....)(.{40})(.)(.)(...)(.{9})(.{9})(.)(.{5})/; more efficiently: unpack("c5 c13 c4 c40 c c c3 c9 c9 c c5", $_); : # ship two values to be whack : $onhand = &packibm($onhand); : $stock_val = &packibm($stock_val); : # print the values : print '"', join('","', $f1, $f2, $f3, $f4, $f5, $f6, $f7, : $onhand, $stock_val, $f8, $f9, $f10), '"', "\n"; I presume we don't need to check for embedded '"'? : } : : sub packibm { : local($_) = @_; : local($tend,$lval) = /(.*)(.)/; : local($get) = &calval($lval); local($tend) = @_; local($get) = $code{ chop($tend) }; : if ($get < 10) { ## meant $get instead of $i, I hope : return($tend * 10 + $get); ## ditto : } else { : return($tend * 10 * -1 + (($get - 10) * -1)); ## ditto : } : } : : ## there is something very non-perlish about the following code, but : ## I couldn't reverse engineer it in the few minutes I had to do this. : ## Larry? : : sub calval { : local($i,$j); : for ($i = 0; $i < 10; $i++) { : for ($j = 0; $j < 3; $j++) { : $look = substr(@lookup[$i],$j,1); : if ($lval =~ $look) { : if ($j == 1) { : $i = $i + 10; : } : return $i; : } : } : } : } This whole subroutine can be replaced by a single associative array lookup. See $code{} above. Actually, now that I glare at the whole thing, you can do packibm like this sub packibm { local($_) = @_; if (tr/}J-R/0-9/) { $_ = -$_; } else { tr/{A-I/0-9/; } $_; } Larry
markb@agora.uucp (Mark Biggar) (06/10/90)
In article <1990Jun6.022140.13168@iwarp.intel.com> merlyn@iwarp.intel.com (Randal Schwartz) writes: > ($f1,$f2,$f3,$f4,$f5,$f6,$f7,$onhand,$stock_val,$f8,$f9,$f10) = > /^(.{5})(.{13})(....)(.{40})(.)(.)(...)(.{9})(.{9})(.)(.{5})/; It is much more efficient to do this with unpack like so: ($f1,$f2,$f3,$f4,$f5,$f7,$onhand,$stock_val,$f8,$f9,$f10) = unpack('a5a13a4a40a1a1a3a9a9a1a5', $_); Two enhancements to unpack would make things like this easier: 1) allow the second argument to default to $_ and 2) if there is anything left over after unpacking it should be returned as the last item in the list. Mark Biggar