home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!usc!news!netlabs!lwall
- From: lwall@netlabs.com (Larry Wall)
- Newsgroups: comp.lang.perl
- Subject: Re: Bug with $number variables ???
- Message-ID: <1992Aug19.065228.8707@netlabs.com>
- Date: 19 Aug 92 06:52:28 GMT
- References: <1992Aug19.040708.519@ucsu.Colorado.EDU>
- Sender: news@netlabs.com
- Organization: NetLabs, Inc.
- Lines: 57
- Nntp-Posting-Host: scalpel.netlabs.com
-
- In article <1992Aug19.040708.519@ucsu.Colorado.EDU> farnham@spot.Colorado.EDU (Farnham Dave) writes:
- : The two lines I'm referring to are:
- : ($login = $1) =~ s/:$//; # remove ':'
- : $shell = $2;
- :
- : In PL-35 "$2" has vanished. It appears that after a
- : substitute all the $number variables get reset to null
- : even if I don't do another capture.
- :
- : This wasn't the case in PL-19. Was I abusing PL-19 or
- : did something break?
-
- It's documented that $1 et al refer back to the last successful pattern
- match (which includes patterns used by substitutes). It was more or
- less a bug in 4.019 that a successful match didn't always invalidate
- prior values. It's best to capture $1, $2, etc. immediately before
- doing another pattern match, unless you really do want $2 from the last
- successful match. I'd usually do either of
-
- if ($line =~ /($search_str).*:.*:.*:.*:.*:(.*)$/) {
- ($login, $shell) = ($1,$2);
- $login =~ s/:$//;
-
- or
-
- if (($login,$shell) = $line =~ /($search_str).*:.*:.*:.*:.*:(.*)$/) {
- $login =~ s/:$//;
-
- By the way, that's a VERY inefficient pattern. Consider that each of
- those .*'s must go to the end of the string and then back off,
- recursively trying all the rest of the patterns after it, which in turn
- go to the end of the string, recursively trying all the rest of the
- patterns after it, which in turn go to the end... You get the picture.
- It'd be faster to use [^:]* when you mean it. Also, you should put an
- o modifier on if the pattern is fixed for a given process run.
-
- It'd be much faster to just take advantage of the fact that .* will match
- everything to the last ":", like this:
-
- $search_str = '^farnham\b';
- ...
- ($login,$shell) = $line =~ /($search_str).*:(.*)$/o;
-
- Or just throw in a
-
- next unless $line =~ /$search_str/o;
- ($login,$pw,$uid,$gid,$gcos,$home,$shell) = split(/:/,$line);
-
- Since you don't execute the split line very often, it doesn't matter
- how long it takes. Even if you did the split on every line it'd still
- be faster than your original pattern.
-
- Rule of Thumb: Never use .* when you can use something else.
-
- Now, you probably knew all that already...
-
- Larry
-