8

Is it possible to do a preg_match on something that shouldn't be a match whilst still returning true?

For example at the moment we have...

if (preg_match('#^Mozilla(.*)#', $agent)) {

We want to check if the Mozilla string is not in $agent but still have preg_match return true.

So we can't change it to...

if (!preg_match('#^Mozilla(.*)#', $agent)) {

Thanks

fire
  • 20,449
  • 16
  • 73
  • 109
  • 4
    I don’t get it. Why can’t you use the latter? – Gumbo Jun 06 '11 at 15:24
  • 1
    the regex part is dynamic, we can change that but we cant change the line it goes though it was just for demonstration – fire Jun 06 '11 at 15:32
  • 1
    But that doesn’t matter. Even if your pattern is not fixed and you want to check whether the pattern does not match, you just need to invert the returned value of `preg_match`. – Gumbo Jun 06 '11 at 15:33
  • 1
    the point is I can't change the logic of the script, if I could I would have just used `if (!preg_match` – fire Jun 06 '11 at 15:36

3 Answers3

13

What you want is a negative lookahead, and the syntax is:

if (preg_match('#^(?!Mozilla).#', $agent)) {

Actually, you can probably get away with just #^(?!Mozilla)# for this. I don't know how PHP will feel about a pattern that's nothing but zero-width tokens, but I've tested it in JavaScript and it works fine.


Edit:

If you want to make sure Mozilla doesn't appear anywhere in the string, you could use this...

if (preg_match('#^((?!Mozilla).)*$#', $agent)) {

...but only if you can't use this!

if (strpos($agent, 'Mozilla') !== false) {
Community
  • 1
  • 1
Justin Morgan
  • 27,557
  • 11
  • 71
  • 100
2
if (preg_match('#^Mozilla(.*)#', $agent) === 0) {

I hope I have not misunderstood your question. preg_match will either return 0 (not found), 1 (found 1 match, does not search for more), or false (some problem occurred). I used === not to return true when false is returned from preg_match.

kapa
  • 72,859
  • 20
  • 152
  • 173
  • `preg_match('#^Mozilla(.*)#', $agent) === 0` is the same as `!preg_match('#^Mozilla(.*)#', $agent)` which the asker stated they cannot do. – Walf Apr 08 '14 at 02:48
  • @walf It is not the same that is the point. 0 == false but 0 !== false. – kapa Apr 08 '14 at 06:35
  • No one is discussing syntax errors in the regexes, and I'd bet `$agent` will always be a string. Hence the `preg_match()` will *never* return a `false` and `!preg_match()` and `preg_match() === 0` produce *exactly the same* boolean. Either way, you didn't read that the regexes are dynamic so the actual code would be like `if (preg_match($test, $agent)) {` and you can't (trivially) choose whether to negate the `preg_match()` dynamically. – Walf Apr 11 '14 at 06:04
2

You can use negative lookahead like this:

#^(?!Mozilla)(.*)#
anubhava
  • 664,788
  • 59
  • 469
  • 547