Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

grepping arrays

by coldfingertips (Pilgrim)
on Jun 21, 2003 at 21:26 UTC ( [id://267870]=perlquestion: print w/replies, xml ) Need Help??

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

Sorry about the two questions in the same day but this is really bugging me. I have a form which I'm using but of course I underestimated the maturity of the people who use it and I got a lot of people tossing in swear words on the sign up form *sigh*.

I tried adding a word filter but when I added it the filter blocked EVERYTHING, even things that weren't in the @ignore didn't go through. Ugh, I am getting frustrated with this one. Why is it blocking things I'm not asking it to?

if(param()){ my $username = param('username'); $username =~ s/\s+\z//; my $askname = param('askname'); $askname =~ s/\s+\z//; my $update = param('update'); if($username){ if($askname){ if(grep($username, @ignore) || grep($askname, @ignore)) { print "That didn't quite work"; exit; } if($update eq "add"){ if(exists $list{$username}){ print "Username already exists in database.\n"; } else{ $list{$username} = $askname; print "Username was added to our system!<p>\n"; } } elsif($update eq "rem"){ if(exists $list{$username}){ delete $list{$username}; print "Account information was removed from the sy +stem.\n"; } else{ print "Oops, it doesn't appear that username is in + our database.\n"; } } } else{ print "For this to work please add your username.\n"; } }else{ print "Unless your name is null, please go back and fill it in +.\n"; } } print end_html();

Replies are listed 'Best First'.
Re: grepping arrays
by BrowserUk (Patriarch) on Jun 21, 2003 at 21:42 UTC

    Your problem is that you misunderstand the way perlfunc:grep works.

    As a hint, this line

    if(grep($username, @ignore) || grep($askname, @ignore)) {

    Should probably look something like this

    if(grep( /$username/, @ignore) || grep( /$askname/, @ignore)) {

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller

Re: grepping arrays
by George_Sherston (Vicar) on Jun 21, 2003 at 21:52 UTC
    I think the main thing going wrong is that your first argument needs to be a block of code rather than a scalar. grep works by running the block of code for each element in the array and returning the number of times it was true (or, if you did @output = grep... it gives you the list of elements from your input array for which it was true... but you don't care about that).

    So this
    if(grep($username =~ m/\b$_\b/, @ignore)) { print "That didn't quite work"; }
    ... may do what you want. (the \bs are so you only catch whole words).

    George Sherston
Re: grepping arrays
by revdiablo (Prior) on Jun 21, 2003 at 22:59 UTC

    Your question has been answered directly by the other fine monks, but I thought it would also be useful to point out that this is a common case where a hash is used instead of an array. Hashes make checks for existence much faster than iterating through your array each time (which is what grep does).

    Here's an example of how you could make your array into a hash:

    my %ignore; @ignore{ @ignore } = (); # note this is a hash slice. the first @ignor +e # is referring to the hash

    And here's how you can check the hash for existence:

    if (exists $ignore{$username} or exists $ignore{$askname}) {
Re: grepping arrays
by grantm (Parson) on Jun 21, 2003 at 23:18 UTC
Re: grepping arrays
by Aristotle (Chancellor) on Jun 22, 2003 at 00:15 UTC
    What you're missing is that the first parameter to grep is supposed to be an expression or a block of code, whose return value determines success or failure of each match. In your case, that return value is found by evaluating $username, which is most likely a true value. So then the grep gives you every single element from @ignore because the expression was true for every one of them. What you really meant to do is either a straight comparison:
    grep $username eq $_, @ignore
    or a pattern match:
    grep /$username/, @ignore
    Note that the second is still an expression, and gets evaluated with each element in @ignore aliased to $_ in turn. You can just write it in this short form because by default, matches are attempted against $_ unless otherwise specified. So the second form is exactly equivalent to this:
    grep $_ =~ /$username/, @ignore

    Makeshifts last the longest.

Re: grepping arrays
by hsweet (Pilgrim) on Jun 21, 2003 at 23:47 UTC
    Looks like your substitutions are a bit too broad. You could put a regex into your if for a simple filter.
    if (/badword/i){print "You are a naughty person...You should wash your + mouth with soap}
    Or you can use substitutions
    s/badword1//; s/badword2//; ..etc;

    Time flies like an arrow, fruit flies like banannas

Re: grepping arrays
by coldfingertips (Pilgrim) on Jun 21, 2003 at 21:48 UTC
    Thank you so much!!

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://267870]
Approved by phydeauxarff
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others examining the Monastery: (3)
As of 2024-06-22 06:15 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.