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