CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
negating a match

 



phil_t
Novice

Feb 13, 2007, 4:31 PM

Post #1 of 13 (1344 views)
negating a match Can't Post

Hi,

I need to come up with a regexp that will negate a match if a particular phrase is found in the string.

For example, it matches if it finds the word 'good' but does not match if it finds the word 'bad' anywhere.

'xxxgoodxxx' (match)

'xxxgoodbadxxx' (not match)

'xxxgoodxxxbad' (not match)

The following code doesn't work, but it's the closest I've been able to come to negating a phrase. The problem is I don't know how to allow an unknown number of characters between 'good' and 'bad'.

$teststr = "xxxgoodxxxbadxxx";
if ($teststr =~ m/good(?!bad)/i){
print "yay\n";
} else {
print "boo\n";
}

Please help! Thanks!


PGScooter
stranger

Feb 13, 2007, 5:06 PM

Post #2 of 13 (1342 views)
Re: [phil_t] negating a match [In reply to] Can't Post


Quote
The problem is I don't know how to allow an unknown number of characters between 'good' and 'bad'.


Hey Phil,

you can use the * to allow for an unknown amount of something. For example .* might fit your needs here (or, you could replace the . if you knew there would only be digits, etc...).

Good luck!

Scott
The more you teach me, the more I learn. The more I learn, the more I teach.


phil_t
Novice

Feb 13, 2007, 5:14 PM

Post #3 of 13 (1338 views)
Re: [PGScooter] negating a match [In reply to] Can't Post

Yeah, I thought .* would work, but it will still produce a match. I think it has something to do with the way the matching works...like it will consider 'goodxxx' a match because there is nothing (satisfies .* requirement) followed by something that is not 'bad' i.e. 'xxx' (satisfies ?!bad requirement). I'm new to Perl, so I'm sure someone more experienced can explain it better.

Anyway, allow me to adjust the code a little bit:

$teststr = "xxxgoodxxxbadxxx";
if ($teststr =~ m/good(?!bad)/i){
print "boo\n";
} else {
print "yay\n";
}

I want to enter the else statement with this $teststr.


PGScooter
stranger

Feb 13, 2007, 5:45 PM

Post #4 of 13 (1334 views)
Re: [phil_t] negating a match [In reply to] Can't Post

Phil
I think you got confused from your previous post, you switched the "yay" and the "boo" but either way I know what you're going for.

oops I messed up :( let me see if I can fix my error
The more you teach me, the more I learn. The more I learn, the more I teach.

(This post was edited by PGScooter on Feb 13, 2007, 5:55 PM)


KevinR
Veteran


Feb 13, 2007, 6:04 PM

Post #5 of 13 (1328 views)
Re: [PGScooter] negating a match [In reply to] Can't Post


Quote
For example, it matches if it finds the word 'good' but does not match if it finds the word 'bad' anywhere.



If by "anywhere" you mean "anywhere":


Code
for ('xxxgoodxxx' , 'xxxgoodbadxxx' , 'xxxgoodxxxbad') {  
if (/good/ and !/bad/) {
print "$_: its good\n";
}
else {
print "$_: its bad\n";
}
}

-------------------------------------------------


phil_t
Novice

Feb 14, 2007, 9:07 AM

Post #6 of 13 (1317 views)
Re: [KevinR] negating a match [In reply to] Can't Post

I'd like to try to match using one condition. I guess my code is more like this:

$teststr = "xxxgoodxxxbadxxx";
$testval = "good(?!bad)"; # can we replace this with something that works?
if ($teststr =~ /$testval/i){
print "boo\n";
} else {
print "yay\n";
}

Again, I want the matching condition such that I enter the else statement with this test string.

Also, I don't mean "anywhere" literally necessarily. I should have said "anywhere after 'good'" if that makes things easier. But literally anywhere would be nice.

I'll modify the code to use two conditions if there's no way to do this using one, I guess.

Thanks for your help!


KevinR
Veteran


Feb 14, 2007, 10:41 AM

Post #7 of 13 (1314 views)
Re: [phil_t] negating a match [In reply to] Can't Post


Code
$testval = qr/good.*?bad/; # can we replace this with something that works? 
foreach my $teststr ('xxxgoodxxx' , 'xxxgoodbadxxx' , 'xxxgoodxxxbad') {
if ($teststr =~ /$testval/) {
print "$teststr: its bad\n";
}
else {
print "$teststr: its good\n";
}
}

-------------------------------------------------


(This post was edited by KevinR on Feb 14, 2007, 10:56 AM)


phil_t
Novice

Feb 14, 2007, 1:04 PM

Post #8 of 13 (1306 views)
Re: [KevinR] negating a match [In reply to] Can't Post

My apologies...I'm not communicating very well in this thread. Thank you, Kevin, for your help. Please bear with me a little more, though.

Let me start over. If I want this to happen:

xxxgoodxxx (match)
xxxgoodbadxxx (not match)
xxxgoodxxxbad (not match)
xxx (not match)

What ONE condition can I create (i.e. what can I assign $testval to be) that will match when it finds 'good', but negate the match if it finds 'bad' afterward? Assuming the code is in the form:

$testval = qr/good.*?bad/; # let's change only this line
foreach my $teststr ('xxxgoodxxx' , 'xxxgoodbadxxx' , 'xxxgoodxxxbad') {
if ($teststr =~ /$testval/) {
print "$teststr: has good but not bad\n";
}
else {
print "$teststr: does not have good or has bad\n";
}
}

I'd be curious to know if we can write the condition such that

xxxbadxxxgood (not match)

but I don't think I need the condition to be that smart quite yet.

Also, I'm a little confused what you did with $testval. I don't quite understand what qr/.../ is doing. Can you explain?

Thanks again for your help. Hope I'm making myself clear in this post.


KevinR
Veteran


Feb 14, 2007, 2:50 PM

Post #9 of 13 (1300 views)
Re: [phil_t] negating a match [In reply to] Can't Post

last try... the fact that you **have** to use one regexp makes me think this is school work.


Code
$testval = qr/good(?!.*?(bad))/; # can we replace this with something that works?  

my @ar = ('xxxgoodxxx' , 'xxxgoodboyxxx' , 'xxxgoodxxxbad' , 'xxxxxxxxxxxx' , 'xxxxxbadxxx', 'xxxgoodbadxxx' , );
foreach my $teststr (@ar) {
if ($teststr =~ $testval) {
print "$teststr: [passed] has 'good' and not bad\n";
}
else {
print "$teststr: [failed] has 'good' and 'bad' or doesn't have 'good'\n";
}
}

-------------------------------------------------


davorg
Thaumaturge / Moderator

Feb 15, 2007, 7:34 AM

Post #10 of 13 (1282 views)
Re: [phil_t] negating a match [In reply to] Can't Post

Read the regex documentation. You're looking for information on "negative lookahead assertions".

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


KevinR
Veteran


Feb 15, 2007, 10:20 AM

Post #11 of 13 (1279 views)
Re: [davorg] negating a match [In reply to] Can't Post


In Reply To
Read the regex documentation. You're looking for information on "negative lookahead assertions".


Note to self: I should have done that in the first place Laugh
-------------------------------------------------


phil_t
Novice

Feb 15, 2007, 11:54 AM

Post #12 of 13 (1276 views)
Re: [KevinR] negating a match [In reply to] Can't Post

Thanks, Kevin! I think that did the trick.

Don't worry, I'm not a student. I just inherited some code at work and I just started learning Perl this week so I can modify it. It'd take too long to explain the situation with this code, so I guess you'll just have to trust me that I ***have*** to use one condition.

But given that it took me so long to figure out what was going on, I think I may do the next guy a favor and do some major surgery to the code so it can look for good words and bad words.

Thanks for all your help!

And thank you, Dave and Scott, for your input too!


KevinR
Veteran


Feb 15, 2007, 12:02 PM

Post #13 of 13 (1273 views)
Re: [phil_t] negating a match [In reply to] Can't Post

you're welcome. Ask more questions if you have any. (in a new thread if its a new question) Wink
-------------------------------------------------

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives