3

I want to use preg_match() in my code, but the result is nothing ... (or null or empty ?)

$domain = "stackoverflow.com";

$uriToTest = "http://stackoverflow.com/";

$pattern = "/^http(s)?://(([a-z]+)\.)*".$domain."/";

echo preg_match($pattern, $uriToTest);

What is the problem?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tata2
  • 893
  • 2
  • 8
  • 14
  • I think you got an error, yes? –  Jul 24 '13 at 09:59
  • 1
    You've got an error - you need to escape your forward slashes. preg_match is returning false – MDEV Jul 24 '13 at 09:59
  • also you need to escape the . in .com. – Tdelang Jul 24 '13 at 10:01
  • Your pattern in invalid. So it should show error. check your error log. Check your pattern. what you want. – Dinuka Thilanga Jul 24 '13 at 10:02
  • Additionally, if you want `$domain` to be matched literally you should use [preg_quote()](http://www.php.net/manual/en/function.preg-quote.php) and hand over the regex delimiter you used. Otherwise regex special characters like the `.` in your string can match things you don't expect. – stema Jul 24 '13 at 10:07
  • If you insert your pattern into http://regex101.com it will automatically test it for you and detect errors. You could have avoided having to ask this question in the first place: http://regex101.com/r/bD3gD7 and a working solution: http://regex101.com/r/uV0eV4 (note, I changed the . in stackoverflow.com to \.) – Firas Dib Jul 24 '13 at 10:20

5 Answers5

3

If you take a look at your pattern, it's this

/^http(s)?://(([a-z]+)\.)*stackoverflow.com/

The delimiter is used as a matching character, and if you had errors turned on, you'd get a "Unknown modifier" error. So first tip: TURN ERROR REPORTING ON!

To fix it, try using a different delimiter, e.g. {}, as it's easier to read than loads of leaning toothpicks...

{^http(s)?://(([a-z]+)\.)*stackoverflow.com}

The other problem is the dot in the $domain becomes a wildcard match - anytime you insert unknown data into a regex, get in the habit of using preg_quote to escape it, e.g.

$pattern = "{^http(s)?://(([a-z]+)\.)*" . preg_quote($domain, '{') . "}";

(Note - nice catch from stema in the comments: if you use a different delimiter, you must pass that preg_quote. It's clever enough to spot paired delimiters, so if you pass { it will also escape }.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
  • 1
    +1 for adding `preg_quote($domain)` to your answer. But shouldn't you add the delimiter as parameter, like `preg_quote($string, '/')`? But I have no idea, how you can add it, if you use a pair of brackets as delimiters. – stema Jul 24 '13 at 10:12
  • that's a really good point - I checked and if you pass '{' it will escape '}' too. I will amend. – Paul Dixon Jul 24 '13 at 10:19
  • I understood what is my problem now. I tried { } but I didn't know preg_quote ... - Why when I'm adding a slash at the end, it didn't work ? Like this : "{^http(s)?://(([a-z]+)\.)*".preg_quote($domain, '{')."/}" (I want to catch this to avoid domain like stackoverflow.com.eu ...) Sorry for my stupid question ... but regex in PHP is not my friend ^^ – Tata2 Jul 24 '13 at 11:39
  • Oh ... ok it's maybe my $domain which was wrong ... :) - Thanks for your help ! – Tata2 Jul 24 '13 at 11:46
0

You're most likely getting an error and preg_match is returning false, as you are not escaping your forward slashes in your expression. Either use something else like a # as the expression delimeter or escape any forward slashes to stop the parser from trying to end the expression (/ should be \/ - or change the / at either end to be #)

//Quick fix to yours
$pattern = "/^http(s)?:\/\/(([a-z]+)\.)*".preg_quote($domain,'/')."/";
//More legible fix
$pattern = '#^https?://(([a-z]+)\.)*'.preg_quote($domain,'#').'#';

Note that you don't need parenthesis around the s in https (unless you're hoping to capture it)

MDEV
  • 10,730
  • 2
  • 33
  • 49
0

You need to escape your forward slashes and the . in the domain name

$domain = "stackoverflow.com";

$uriToTest = "http://stackoverflow.com/";

$escapedDomain = str_replace('.', '\.', $domain);

$pattern = "/^http(s)?:\/\/(([a-z]+)\.)*".$escapedDomain."/";

echo preg_match($pattern, $uriToTest);
MajorCaiger
  • 1,893
  • 1
  • 12
  • 18
0

If you were using T-Regx, then this exception would be thrown immediately:

$domain = "stackoverflow.com";
$uriToTest = "http://stackoverflow.com/";

try
{
    pattern("/^http(s)?://(([a-z]+)\.)*" . $domain . '/')->match($uriToTest);
}
catch (SafeRegexException $e) {
    echo $e->getMessage();    // `Unknown modifier '/'`
}

But also!! T-Regx can automatically add delimiters, so you can go

pattern("^http(s)?://(([a-z]+)\.)*" . $domain)->match($uriToTest);

and it would automatically add a suitable delimiter for you.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Danon
  • 2,771
  • 27
  • 37
-1
  $domain = "stackoverflow.com";

  $uriToTest = "http://stackoverflow.com/";

  $pattern = "^http(s)?://(([a-z]+)\.)*" . $domain . "^";

  preg_match($pattern, $uriToTest, $matches);
  print_r($matches);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
M Shahzad Khan
  • 935
  • 1
  • 9
  • 22
  • Why are you using the start of string anchor `^` as regex delimiter? – stema Jul 24 '13 at 10:03
  • Inorder to avoid error. preg_match delimiter must be started from backslash. you can write in this way as well $pattern = "^\http(s)?://(([a-z]+)\.)*".$domain."^"; – M Shahzad Khan Jul 24 '13 at 10:07
  • I agree, I think that's confusing advice – Paul Dixon Jul 24 '13 at 10:09
  • But you are introducing another error. The OP already used the regex special character `^` in the regex to match the start of the string. – stema Jul 24 '13 at 10:09