PHP Preg_Match With Working Regex

PHP preg_match function not working as expected

There are several issues with your code.

  1. If you're using single quotes for the pattern and want to match a literal backslash, you need to use at least \\\ or even \\\\ to produce an escaped backslash \\. Just echo your pattern if unsure.

  2. Instead of using the global flag g which is not available in PHP use preg_match_all. If it matches, it returns the number of matches. You can check match condition by preg_match_all(...) > 0

  3. Unsure about ^ in [\\^]. if you don't need it, drop it. Further [0-9] can be reduced to \d. Also I would add a word boundary \b after \d{4} if something like \u12345 should not be matched.

See this PHP demo at tio.run

$pattern = '/\\\u\d{4}\b/i';
# echo $pattern;

if(preg_match_all($pattern, $data['title'], $matches, PREG_OFFSET_CAPTURE) > 0){
print_r($matches[0]);
} else{
echo "Not Found";
}

Preg_match doesn't work when pattern and subject inside preg_quote - PHP

You shouldn't use preg_quote($message) for your original text in the subject to search . This is ONLY to make sure any text is a valid regex expression. If you echo out the result of this you get...

My two great things in life are spaghetti and bolognese Order yours #online from Ammou Pizza in Limassol\!

foody\.com\.cy/ammou\-pizza

and as you can see it has encoded ammou\-pizza. This isn't what you want, the \- sequence is only needed as - is means something different to regex other than a simple dash.

Just use...

if(preg_match('#' . preg_quote("ammou-pizza") . '#',  $message))

Php preg_match not working with óá

While it seems you may need to include several other accented and/or non-English letters, I will only include the letters you mentioned.

An alternative and super-lenient pattern (perhaps not secure enough) would be \\\:[^\/]+

Code:

$route['url'] ="/test/x/:name/123";
$reqUrl = "/test/x/hállò/123";

echo "Input:\n";
var_export(preg_quote($route['url']));

$pattern="@^".preg_replace('/\\\:[a-zA-Z0-9áò_-]+/','([a-zA-Z0-9áò_-]+)',preg_quote($route['url']))."$@D";
// ^^ new letters here: ^^

if(preg_match($pattern, $reqUrl, $matches)) {
echo "\n\nOutput\n";
var_export($matches);
}else{
echo "\n\nNo Match";
}

Displays:

Input:
'/test/x/\\:name/123'

Output
array (
0 => '/test/x/hállò/123',
1 => 'hállò',
)

My pattern isn't matching a ISO style date, why?

Why use regex? Use DateTime class.

function validateDate($date, $format = 'Y-m-d H:i:s')
{
$d = DateTime::createFromFormat($format, $date);
return $d && $d->format($format) == $date;
}

You can use this function for all kind of date/time validations. Examples:

var_dump(validateDate('2012-02-28 12:12:12')); # true
var_dump(validateDate('2012-02-30 12:12:12')); # false
var_dump(validateDate('2012-02-28', 'Y-m-d')); # true
var_dump(validateDate('28/02/2012', 'd/m/Y')); # true
var_dump(validateDate('30/02/2012', 'd/m/Y')); # false
var_dump(validateDate('14:50', 'H:i')); # true
var_dump(validateDate('14:77', 'H:i')); # false
var_dump(validateDate(14, 'H')); # true
var_dump(validateDate('14', 'H')); # true

var_dump(validateDate('2012-02-28T12:12:12+02:00', 'Y-m-d\TH:i:sP')); # true
# or
var_dump(validateDate('2012-02-28T12:12:12+02:00', DateTime::ATOM)); # true

var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', 'D, d M Y H:i:s O')); # true
# or
var_dump(validateDate('Tue, 28 Feb 2012 12:12:12 +0200', DateTime::RSS)); # true
var_dump(validateDate('Tue, 27 Feb 2012 12:12:12 +0200', DateTime::RSS)); # false
# ...

php preg_match and regex regular expression

Note that inside a double-quoted string, you need to use double backslash to escape regex shorthand classes.

You can use your regex inside a preg_replace function inside single quotes so that you do not have to double backslashes:

$title= "The Big Bang Theory S04E05";
$ret=preg_replace('/^(.*)[.\s]s\d{1,20}e\d{1,100}(.*)/i', '\1\2', $title);
echo $ret;

See IDEONE demo. Result: The Big Bang Theory.

The back-references \1\2 will restore the substrings before and after the episode substring.

Since you are using /i modifier, you need not use [eE] or [Ss], just use single letters in any case.

To return the substring before the episode and the episode substring itself, just use the capturing groups with preg_match like here:

$title= "The Big Bang Theory S04E05";
$ret=preg_match('/^(.*)[.\s](s\d{1,20}e\d{1,100})/i', $title, $match);
echo $match[1] . PHP_EOL; // => The Big Bang Theory
echo $match[2]; // => S04E05

See another demo

preg_match pattern dosn't work in php v 5

Brief

Your pattern is /^\9\d{9}/. Note that there's a \9 in there. This is usually interpreted as a backreference (which is what's happening in your earlier version of PHP). I guess the interpreter is now smarter and realizes your subpattern \9 doesn't exist and so it understands it as a literal 9 instead.

Edit - Research

I dug deeper into this change in behaviour and in PHP 5.5.10 they upgraded PCRE to version 8.34. Looking through the changelogs for PCRE, now, I discovered that version 8.34 of PCRE introduced the following change:


  1. Perl has changed its handling of \8 and \9. If there is no previously
    encountered capturing group of those numbers, they are treated as the
    literal characters 8 and 9 instead of a binary zero followed by the
    literals. PCRE now does the same.

Code

Use this regex instead.

/^9\d{9}/

Usage

See code in use here

<?php

$string = '9301234567';
if( preg_match('/^9\d{9}/', $string) )
{
$string = '0+1'.$string ;
print $string ;
}

php preg_match() not working, find a var

Here is a more efficient solution:

Pattern (Demo):

/\$adv\[\K[^]]*?(?=\])/

PHP Implementation:

if(preg_match('/\$adv\[\K[^]]*?(?=\])/','this is example $adv[name]',$itext)){
echo $itext[0];
}

Output for $itext:

name

Notice that by using \K to replace the capture group, the targeted string is returned in the "full string" match which effectively reduces the output array by 50%.

You can see the demo link for explanation on individual pieces of the pattern, but basically it matches $adv[ then resets the matching point, matches all characters between the square brackets, then does a positive lookahead for a closing square bracket which will not be included in the returned match.

Regardless of if you want to match different variable names you could use: /\$[^[]*?\[\K[^]]*?(?=\])/. This will accommodate adv or any other substring that follows the dollar sign. By using Negated Character Classes like [^]] instead of . to match unlimited characters, the regex pattern performs more efficiently.

If adv is not a determining component of your input strings, I would use /\$[^[]*?\[\K[^]]*?(?=\])/ because it will be the most efficient.

php preg_match - pattern for number at end of string, always preceded by space, in turn preceded by any characters?

You can try this approach:

preg_match("/^\S.* (\b\d+)$/", $str, $matches);
echo end($matches)."\n";

For instance if you use the following variable:

$str = "1234 lkjsdhf ldjfh  1223";

The call to end($matches) will return 1223

Whereas if you use the following variable:

$str = " 1212";

call to end($matches) will remain empty.



Related Topics



Leave a reply



Submit