SPUG: ifs and whiles and hashes...

Tim Maher/CONSULTIX tim at consultix-inc.com
Wed Aug 18 18:34:56 CDT 1999


>> Message submitted at: Wed Aug 18 16:34:56 PDT 1999
X-Mailer: ELM [version 2.4 PL25]
MIME-Version: 1.0
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Length: 2805      

According to Ryan Forsythe:
> 
> hi, it's ryan the perl newbie again, with another (probably) simple
> question...
> 
> i'm writing a program which opens a text file, searches each line, and
> extracts data from it and sticks it in a hash...well, that's what it's
> supposed to do.  here's a simplification of the loop i'm having problems
> with:
> 
> while (defined($dbaseLine = <DATABASE>))  {
> 
> 	#code here...
> 
> 	if ($dbaseLine =~ m/^\"(?:.*)\",\"(.*)\",\"(.*)\"/)  {
> 		
> 		$hash{'key1'} = $1;
> 		$hash{'key2'} = $2;
> 		#etc...
> 	}  else  {
> 		next;
> 	}
> }
> 
> however, my program has 26 of these '\"(.*)\",' in the 'if
> ($dbaseLine...' test.  when i run it, it assigns the $dbaseLine variable
> okay, but when it gets to that if test, it locks up and i watch perl's
> cpu time go up to 99%.  i'm assuming it's getting in an infinite loop,

I think it's looking ahead to see how much data each .* part can gobble
up without invalidating the rest of the complete match,  and repeatedly
back-tracking and starting over until it finds the maximal match for each
.* part that allows the overall match.  This is exactly where you want to
use the "stingy" match option, .*?, which will  get the shortest match
and obviate the need for all the scanning-ahead and back-tracking.
> 	if ($dbaseLine =~ m/^\"(?:.*?)\",\"(.*?)\",\"(.*?)\"/)  {

Regarding simplifying the writing, you could grab each match
from a separate iteration of a loop with the matching operator as
the test condition, but then you'd have to implement your own counter
to make sure you got all 26 matches, so it's probably easier just to write
the hairy RE and go for the match all at once. 

I think you can also do something  like:
	(the_match){26}
to say you want 26 of those matches, but I wasn't getting 26 variables
populated in my test case, just $1 holding the last match.  There might
be a way to do this, but off the top of my head (here on my reclining
chair in full sunlight, without recourse to Friedl's book) this is as
close as I can come right now! 8-}

Can somebody else tell Ryan how to do this?


> but why?  i don't understand how an if can cause and infinite loop,
> especially when it doesn't affect the test variable of the while it's
> wrapped in (if that makes any sense to anybody :))
> 
> btw, is there any shorter way to write that 'if' that still stores
> substrings?
> 
> --ryan

*==================================================================*
| Tim Maher, PhD  CEO, Consultix &    (206) 781-UNIX/8649          |
|      Pacific Software Gurus, Inc.   Email: tim at consultix-inc.com |
| "The UNIX/Perl Training Experts"    http://www.consultix-inc.com |
|CLASSES: Shell+Utils: 8/23-27; Perl: 8/30-9/1;  Perl Modules: 9/2;|
*==================================================================*

 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    POST TO: spug-list at pm.org        PROBLEMS: owner-spug-list at pm.org
 Seattle Perl Users Group (SPUG) Home Page: http://www.halcyon.com/spug/
 SUBSCRIBE/UNSUBSCRIBE: Replace ACTION below by subscribe or unsubscribe
        Email to majordomo at pm.org: ACTION spug-list your_address





More information about the spug-list mailing list