http://qs1969.pair.com?node_id=321301

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I have the following script segment:
open PAGE, "$data_reg" or die "Can't open $data_reg: $!"; while (my $line = <PAGE>) { ($username_db,$password_db,$email_address_db,$name_db,$spare) = sp +lit "\t",$line; if ($username eq $username_db) { $check++; } else { $problem = "Unfortunately we cannot find reference to the +username supplied.<br> Please check with the webmaster of this site."; print "$problem"; exit; } } close PAGE;
This seemes always to fail ar the first pass and does not check the rest of the lines.

I can get round this by taking the 'else' statement out and doing (after close PAGE):

if ($check){ #do something; } else { $problem etc. }
But I don't want to!

can someone tell me why the original fails to lookup the whole file?

Replies are listed 'Best First'.
Re: searching a file
by borisz (Canon) on Jan 14, 2004 at 16:53 UTC
    You should check that no username match the username_db
    open PAGE, "$data_reg" or die "Can't open $data_reg: $!"; while (my $line = <PAGE>) { ($username_db,$password_db,$email_address_db,$name_db,$spare) = sp +lit "\t",$line; if ($username eq $username_db) { $check++; $found_user++; last; # exit while } } unless ( $found_user ) { $problem = "Unfortunately we cannot find reference to the username s +upplied.<br> Please check with the webmaster of this site."; print "$problem"; exit; } close PAGE;
    Boris
Re: searching a file
by Fletch (Bishop) on Jan 14, 2004 at 16:52 UTC

    It'll always fail unless the username in question is on the first line because that's what you've written. You want to look at all the lines, but if any line doesn't match you're exiting. What you want to do is last out of the while loop if you find a match and to use a flag in a conditional after the while loop's done.

Re: searching a file
by blue_cowdawg (Monsignor) on Jan 14, 2004 at 16:50 UTC

    Your logic is exiting on the first lookup AM.


    Peter L. Berghold -- Unix Professional
    Peter at Berghold dot Net
       Dog trainer, dog agility exhibitor, brewer of fine Belgian style ales. Happiness is a warm, tired, contented dog curled up at your side and a good Belgian ale in your chalice.
Re: searching a file
by naChoZ (Curate) on Jan 14, 2004 at 16:55 UTC

    The exit is causing the program to end. How are you definining $username? Did you try printing $username and $username_db to be sure the values are what you expect before doing the if statement?

    --
    Diplomacy is the art of saying "Nice doggie" until you can find a rock.
    naChoZ

Re: searching a file
by Roy Johnson (Monsignor) on Jan 14, 2004 at 16:59 UTC
    It fails to lookup the whole file because you exit upon finding a problem.

    The PerlMonk tr/// Advocate
Re: searching a file
by jonadab (Parson) on Jan 14, 2004 at 18:52 UTC

    Another way to do this is using grep:

    # This code is untested. open PAGE, "$data_reg" or die "Can't open $data_reg: $!"; my @matchinglines = grep { $username eq (split "\t", $_)[0]; } <PAGE>; (print "<div>Unfortunately we cannot find reference to the username supplied.</div> <div>Please check with the webmaster of this site." and exit) unless @matchinglines; close PAGE;

    The advantage of this way is that the code is shorter and less convoluted, thus easier to follow. The disadvantage is that it slurps the whole file into a list, so if the file is really huge it can be a memory overhead problem.

    I can get round this by taking the 'else' statement out and doing (after close PAGE) [...] But I don't want to!

    You didn't say why it is that you don't want to put the error-handling outside the loop. Did you realise that the way you have the code, the error handling happens after each line? So, for each line in the file that doesn't match the supplied username, the error condition would be triggered. (I say "would be", because the exit stops it after the first time.) Why is it that this is preferable to having the error condition checked for just once, after all the lines have been read?

    Also, when you do check++, does your real code do something else, like save the line, or is it really just a check? Because, if it's really just a binary check, you could save time if you skip reading the rest of the lines. I don't know how much performance matters for your application, so this is just a thought.


    $;=sub{$/};@;=map{my($a,$b)=($_,$;);$;=sub{$a.$b->()}} split//,".rekcah lreP rehtona tsuJ";$\=$ ;->();print$/