in reply to Re: Re: Simple for some.
in thread Compare two lists of words

The first problem with your code, and the reason it always comes back with "Found it. ", it this line:

if (/$hit[0]/ || /$strike[1]/) {

Here you are asking if either $hit[0] or $strike[1] is found within this line. Which means that it only needs for one of these to appear anywhere in the file, and "Found it." will be printed. In order to check that both exist in the same line you would need to do something like:

if (/$hit[0] && /$strike[1]/) {

However, that's still not good enough because ( I'm going to use $userid instead of $hit[0] and $password instead of $strike[1] ).

Let's say $userid = 'fred' and $password = 'mother' and the associated email_id is fred@yahoo.com, when the line of your array containing:

1028804576 fred@yahoo.com fred mother

is checked, then if ( /$userid/ && /$password/) { will match and your on your way, but what happens if a line earlier in your file contained

1028804571 mum@yahoo mother fred # This would also match, and +would be found earlier # ^^^^^^ ^^^^ 1028804572 wilfred@hotmail wilf mother # This would also match + and be found earlier # ^^^^ ^^^^^^

So, the next step is to make sure that a) they both appear in the right order and b) they are at the end of the line, something like this:

if ( /$userid[ \t]+$password$/ ) { # [ \t]+ means one or more spaces or tabs ($/) means at the end o +f the line.

This is better, but now think about what happens if some nasty user fills in ".*" for $userid and $password?

This means that the regex /$userid[ \t]+$password$/ will become /.*[ \t]+.*$/, which will match any line that has a space or a tab in it! Again, not what you want at all.

The way to avoid this is to use the quotemeta function or the \Q\E metaquote pairings see perlman:perlre.

$userid = quotemeta $userid; $password = quotemeta $password; if ( /$userid[ \t]+$password$/ ) {

or just

if ( /\Q$userid\E[ \t]+\Q$password$\E/ ) {

So, a version of your code with the minimum changes to make it work would look something like

Updated again to cover the hole Arien points out below!

#! perl -w my $flag = 0; for (@raw_data) { if ( defined $hit[0] and $hit[0] # has a value that is no +n-null and defined $strike[1] and $strike[1] # ditto and /\Q$hit[0]\E[ \t]+\Q$strike[1]\E$/) { print "Found it."; $flag = 1; last; } } if (! $flag) { # didn't find it in the array print "didnt find it"; }

That said, reading your database into a hash as described in jeffa's and other answers is almost certainly a better way of doing what you want to do, and my earlier advice about reading perlman:perlsec and using the -T switch still stands.

Finally, it would be a good idea to read Writeup Formatting Tips before you post another question to save the editors from having to reformat your posts to make them readable.


What's this about a "crooked mitre"? I'm good at woodwork!

Replies are listed 'Best First'.
Re(4): Simple for some.
by Arien (Pilgrim) on Aug 18, 2002 at 19:14 UTC

    I'm sorry, but this still isn't good enough:

    if (/\Q$hit[0]\E[ \t]+\Q$strike[1]\E$/) {

    Now you just need a valid password, as long as you leave the username ($hit[0]) empty.

    — Arien