Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!ames!elroy.jpl.nasa.gov!jpl-devvax!lwall From: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Newsgroups: comp.lang.perl Subject: Re: variable is numeric? Message-ID: <7449@jpl-devvax.JPL.NASA.GOV> Date: 17 Mar 90 02:59:13 GMT References: <16918@orstcs.CS.ORST.EDU> <7443@jpl-devvax.JPL.NASA.GOV> <16943@orstcs.CS.ORST.EDU> Reply-To: lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) Organization: Jet Propulsion Laboratory, Pasadena, CA Lines: 92 In article <16943@orstcs.CS.ORST.EDU> pvo@sapphire.OCE.ORST.EDU (Paul O'Neill) writes: : A lot of survey data comes through this lab. Data from different institutions : using different instruments in different formats. Some is in feet that needs : converting to meters. : : Almost invariably, the data needing conversion appear as a triplet of : numbers. What a great job for perl! : : My perl script to convert surveyed feet to surveyed meters justs looks for : a line w/ 3 consecutive numbers and multiplies all such triplets by : 0.3048006. : : BUT IT'S UGLY: : : ----------------------------------------------------------------------- : #!/usr/local/bin/perl : # : # ft2m_any.perl : # 27 feb 90 : # Paul V. O'Neill -- Coastal Imaging Lab, OSU, Corvallis, OR 97331 : # : # feet to meters convertion on lines consisting of 3 consecutive numbers : # leave other lines alone : # : format STDOUT = : @<<<<<< @<<<<<< @<<<<<<< : $meters[0], $meters[1], $meters[2] : . : : while (<>) { # get a line at a time : $save = $_; : @feet = /([0123456789.]*)\s*([0123456789.]*)\s*([0123456789.]*)\s*/; : if($feet[2]) { : @meters = grep($_ *= .304800609601, @feet ); : write; : } else { : print $save; : } : } : -------------------------------------------------------------- : : [0123456789.] seems a gross way to identify a number. And "10.33.9" would : pass the test. You can say [0-9.]. Or [\d.]. If you're worried about multiple dots, I'd suggest \d*\.?\d+ or \d+\.?\d*. Do you allow ".1" or only "0.1"? : If perl knows that a variable is numeric (automagical increment writeup) : why can't I know? I'd much prefer to split the current line and do some : cute, canonical test on each member of @_ for "numberness." What's the matter with (assuming no leading .'s) @feet = grep(/^\d+\.?\d*$/,split(' ')); if (@feet == 3) { # found 3 numbers (patchlevel 12) Or maybe, if your numbers are always greater than 0 @feet = grep($_ + 0, split(' ')); Of course, if that's true, there's always if ($feet[0] * $feet[1] * $feet[2]) { If they can be zero, how about @feet = grep($_ + 0 || /^0\.?0*$/, split(' ')); or @feet = grep($_ + 0 || /^0?\.?0+$/, split(' ')); Presuming your triples are on a line by themselves, and you don't care much about how much whitespace or precision you end up with, you could probably write your script as while (<>) { @nums = grep((s/\.//,/^-?\d+$/), split(' ')); s/([\d.]+)/$1 * .304800609601/eg if @nums == 3; print; } I would try to avoid the write in any case: while (<>) { @meters = grep(/^0\.?0*$/ || $_ *= .304800609601, split(' ')); $_ = sprintf(" %7.7s %7.7s %8.8s\n",@meters) if @meters == 3; print; } This can be reduced to #!/usr/local/bin/perl -p @meters = grep(/^0\.?0*$/ || $_ *= .304800609601, split(' ')); $_ = sprintf(" %7.7s %7.7s %8.8s\n",@meters) if @meters == 3; In general, perl never knows whether your string looks like a number, because it just assumes it's a number and forces the issue whenever you treat it like a number. It would be wasting CPU to do otherwise. Seeing that your variable != 0 is at least indicative that the front of the string looked like a non-zero number. Other than than, you have to be explicit. Larry