PHP preg_match function not working as expected
There are several issues with your code.
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.Instead of using the global flag
g
which is not available in PHP usepreg_match_all
. If it matches, it returns the number of matches. You can check match condition bypreg_match_all(
...) > 0
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:
- 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
Best Way to Get Result Count Before Limit Was Applied
Detecting Request Type in PHP (Get, Post, Put or Delete)
Getting Raw SQL Query String from Pdo Prepared Statements
Continue Processing PHP After Sending Http Response
Highlight the Difference Between Two Strings in PHP
Pass a PHP Array to a JavaScript Function
Convert Multidimensional Array into Single Array
Get the First Element of an Array
How to Get a Hex Dump of a String in PHP
Form Inside of $.Load Not Posting Correctly
Https and Ssl3_Get_Server_Certificate:Certificate Verify Failed, Ca Is Ok