I'm using the following regex to parse a date in dd/mm/yyyy format:
^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$
I've checked it on strfriend and it all looks ok. However, when testing for it in PHP with preg_match it doesn't recognize it:
if(!preg_match("/^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$/",trim($_POST['dob']))){
$error .= "You must enter a valid date of birth.";
}
This happens with input such as 29/10/1987 and 01-01-2001, and I'm not sure why it doesn't work!
I also get the following warning:
Warning: preg_match() [function.preg-match]: Unknown modifier '.' in /home/queensba/public_html/workers/apply.php on line 18
which I'm not sure how to interpret.
If you use '/' in within your regex, you may not start/end the regular expression with it. Just replace it with '#' for example.
if(!preg_match("#^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$#",trim($_POST['dob']))){
$error .= "You must enter a valid date of birth.";
}
(BTW, Modifiers would come after the final delimiter '#'. So the warning appeared because PHP thought the regex would end after the second '/'.)
The / inside your regex trip up PHP because it thinks they are your regex delimiters.
Try
if(!preg_match("#^(0[1-9]|[12][0-9]|3[01])[- /.](0[1-9]|1[012])[- /.](19|20)\d\d$#",trim($_POST['dob']))){
$error .= "You must enter a valid date of birth.";
}
Since you are using /.../ as the pattern delimiter you need to escape all other instances of / like \/ alternative is to use a different delimiter like ~
Don't use double quotes for strings, they're for templates.
If you have '/' in your pattern, you cannot begin and end it with the same character, do it with "%","#" or any other characters...
If you have unicode string, you have to use the "u" flag.
Related
I'm getting this odd error in the preg_match() function:
Warning: preg_match(): Compilation failed: range out of order in character class at offset 54
The line which is causing this is:
preg_match("/<!--GSM\sPER\sNUMBER\s-\s$gsmNumber\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s$gsmNumber\s-\sEND-->/s", $fileData, $matches);
What this regular expression does is parse an HTML file, extracting only the part between:
<!--GSM PER NUMBER - 5550101 - START-->
and:
<!--GSM PER NUMBER - 5550101 - END-->
Do you have a hint about what could be causing this error?
Hi I got the same error and solved it:
Warning: preg_match(): Compilation failed: range out of order in character class at offset <N>
Research Phase:
.. Range out of order .. So there is a range defined which can't be used.
.. at offset N .. I had a quick look at my regex pattern. Position N was the "-". It's used to define ranges like "a-z" or "0-9" etc.
Solution
I simply escaped the "-".
\-
Now it is interpreted as the character "-" and not as range!
If $gsmNumber contains a square bracket, backslash or various other special characters it might trigger this error. If that's possible, you might want to validate that to make sure it actually is a number before this point.
Edit 2016:
There exists a PHP function that can escape special characters inside regular expressions: preg_quote().
Use it like this:
preg_match(
'/<!--GSM\sPER\sNUMBER\s-\s' .
preg_quote($gsmNumber, '/') . '\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s' .
preg_quote($gsmNumber, '/') . '\s-\sEND-->/s', $fileData, $matches);
Obviously in this case because you've used the same string twice you could assign the quoted version to a variable first and re-use that.
This error is caused for an incorrect range. For example: 9-0 a-Z
To correct this, you must change 9-0 to 0-9 and a-Z to a-zA-Z
In your case you are not escaping the character "-", and then, preg_match try to parse the regex and fail with an incorrect range.
Escape the "-" and it must solve your problem.
I was receiving this error with the following sequence:
[/-.]
Simply moving the . to the beginning fixed the problem:
[./-]
While the other answers are correct, I'm surprised to see that no-one has suggested escaping the variable with preg_quote() before using it in a regex. So if you're looking to match an actual bracket or anything else that means something in regex, that'll be converted to a literal token:
$escaped = preg_quote($gsmNumber);
preg_match( '/<!--GSM\sPER\sNUMBER\s-\s'.$escaped.'\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s'.$escaped.'\s-\sEND-->/s', $fileData, $matches);
You probably have people insert mobile numbers including +, -, ( and/or ) characters and just use these as is in your preg_match, so you might want to sanitize the data provided before using it (ie. by stripping these characters out completely).
This is a bug in several versions of PHP, as I have just verified for the current 5.3.5 version, as packaged with XAMPP 1.7.4 on Windows XP home edition.
Even some very simple examples exhibit the problem, e.g.,
$pattern = '/^[\w_-. ]+$/';
$uid = 'guest';
if (preg_match($pattern, $uid)) echo
("<style> p { text-decoration:line-through } </style>");
The PHP folks have known about the bug since 1/10/2010.
See http://pear.php.net/bugs/bug.php?id=18182.
The bug is marked "closed" yet persists.
regex:^([^\/])/([A-Z])([^\/]+)/([^\/]+)/$
string to match: http://127.0.0.1:8008/BeiJing/FangChan/
I use preg_match() to test
if (preg_match('/^([^\/])/([A-Z])([^\/]+)/([^\/]+)/$/',"http://127.0.0.1:8008/BeiJing/FangChan/",$match))
print $match[0];
else
print 'not match';
but get a Warning: preg_match() [function.preg-match]: Unknown modifier '('
Can anyone help me write this regex so it's valid for the preg_match function? I've tried a ton of different ideas but I'm really not too knowledgeable with regex.
/ is what is indicating the start and the end of the pattern in your example, whatever comes after the pattern is a modifier.
So this:
/^([^/])/([A-Z])([^/]+)/([^/]+)/$/
Gets read as this:
/^([^/])/
With modifiers ([A-Z])([^/]+)/([^/]+)/$/
You have to escape all /'s or change the start and end indicator:
#^([^/])/([A-Z])([^/]+)/([^/]+)/$#
You need to escape the / you use by putting a \ in front of it. Or change the first and last / to something else like:
if (preg_match('|^([^/])/([A-Z])([^/]+)/([^/]+)/$|',"http://127.0.0.1:8008/BeiJing/FangChan/",$match)) print $match[0]; else
But this regexp will not match the url.
I am trying to match a Youtube URL with regex to see if it is valid. This is my code:
if(preg_match('\bhttp://youtube.com/watch\?v=.*\b', $link))
{
echo "matched youtube";
}
But I'm getting an error:
Warning: preg_match() [function.preg-match]: Delimiter must not be alphanumeric or backslash in C:\xampp\htdocs\ajax\youtube.php on line 22
I'll admit I am a complete novice to regular expressions and I don't understand them much but I am trying to learn as I do this. I made the above regex using this online regex tool:
http://gskinner.com/RegExr/
and it works there. So what am I doing wrong and is there a better way to validate a youtube URL?
Thanks. :)
There's really no need for preg_match here:
$url = "http://youtube.com/watch?v=abc";
if(strpos($url, "http://youtube.com/watch?v=") === 0) {
echo "Valid";
}
PCRE require delimiters that separate the regular expressions and optional modifiers.
In this case the \ is assumed but \ is not a valid delimiter (see error message). Use a different character like ~:
preg_match('~\bhttp://youtube\.com/watch\?v=.*\b~', $link)
You should add addition delimeters to your regexp. This is used to supply optional parameters:
preg_match('"\bhttp://youtube.com/watch\?v=.*\b"', $link)
Symbol / is usually used as regexp delimeter, but in your case it'll force inner / to be escaped. So for more clear view I suggest to use ".
When using preg_match, then the regexp needs to be enclosed with proper delimiters.
For example:
preg_match('/\bhttp://youtube.com/watch\?v=.*\b/', $link)
In your example \b stands for word boundary, this is not a valid alphanumeric delimiter, hence the error message
I'm getting this odd error in the preg_match() function:
Warning: preg_match(): Compilation failed: range out of order in character class at offset 54
The line which is causing this is:
preg_match("/<!--GSM\sPER\sNUMBER\s-\s$gsmNumber\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s$gsmNumber\s-\sEND-->/s", $fileData, $matches);
What this regular expression does is parse an HTML file, extracting only the part between:
<!--GSM PER NUMBER - 5550101 - START-->
and:
<!--GSM PER NUMBER - 5550101 - END-->
Do you have a hint about what could be causing this error?
Hi I got the same error and solved it:
Warning: preg_match(): Compilation failed: range out of order in character class at offset <N>
Research Phase:
.. Range out of order .. So there is a range defined which can't be used.
.. at offset N .. I had a quick look at my regex pattern. Position N was the "-". It's used to define ranges like "a-z" or "0-9" etc.
Solution
I simply escaped the "-".
\-
Now it is interpreted as the character "-" and not as range!
If $gsmNumber contains a square bracket, backslash or various other special characters it might trigger this error. If that's possible, you might want to validate that to make sure it actually is a number before this point.
Edit 2016:
There exists a PHP function that can escape special characters inside regular expressions: preg_quote().
Use it like this:
preg_match(
'/<!--GSM\sPER\sNUMBER\s-\s' .
preg_quote($gsmNumber, '/') . '\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s' .
preg_quote($gsmNumber, '/') . '\s-\sEND-->/s', $fileData, $matches);
Obviously in this case because you've used the same string twice you could assign the quoted version to a variable first and re-use that.
This error is caused for an incorrect range. For example: 9-0 a-Z
To correct this, you must change 9-0 to 0-9 and a-Z to a-zA-Z
In your case you are not escaping the character "-", and then, preg_match try to parse the regex and fail with an incorrect range.
Escape the "-" and it must solve your problem.
I was receiving this error with the following sequence:
[/-.]
Simply moving the . to the beginning fixed the problem:
[./-]
While the other answers are correct, I'm surprised to see that no-one has suggested escaping the variable with preg_quote() before using it in a regex. So if you're looking to match an actual bracket or anything else that means something in regex, that'll be converted to a literal token:
$escaped = preg_quote($gsmNumber);
preg_match( '/<!--GSM\sPER\sNUMBER\s-\s'.$escaped.'\s-\sSTART-->(.*)<!--GSM\sPER\sNUMBER\s-\s'.$escaped.'\s-\sEND-->/s', $fileData, $matches);
You probably have people insert mobile numbers including +, -, ( and/or ) characters and just use these as is in your preg_match, so you might want to sanitize the data provided before using it (ie. by stripping these characters out completely).
This is a bug in several versions of PHP, as I have just verified for the current 5.3.5 version, as packaged with XAMPP 1.7.4 on Windows XP home edition.
Even some very simple examples exhibit the problem, e.g.,
$pattern = '/^[\w_-. ]+$/';
$uid = 'guest';
if (preg_match($pattern, $uid)) echo
("<style> p { text-decoration:line-through } </style>");
The PHP folks have known about the bug since 1/10/2010.
See http://pear.php.net/bugs/bug.php?id=18182.
The bug is marked "closed" yet persists.
Does any body know why the filter_var() function below is generating the warning? Is there a limit on how many characters can be in a character class?
$regex = "/^[\w\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057\072\073\074\075\076\077\100\133\134\135\136\140\173\174\175\176]*$/";
$string = "abc";
if(!filter_var($string, FILTER_VALIDATE_REGEXP, array("options" => array("regexp"=>$regex))))
{
echo "dirty";
}
else
{
echo "clean";
}
Warning: filter_var() [function.filter-var]: Unknown modifier ':'
Your regex is interpreted by PHP as this string :
string '/^[\w!"#$%&'()*+,-./:;<=>?#[\]^`{|}~]*$/' (length=40)
(use var_dump on $regex, and you'll get that)
Right in the middle of your regex, so, there is a slash ; as you are using a slash to delimit the regex (it's the first character of $regex), PHP thinks this slash in the middle is marking the end of the regex.
So, PHP thinks your regex is actually :
/^[\w!"#$%&'()*+,-./
Every character that comes after the ending slash are interpreted as modifiers.
And ':' is not a valid modifier.
You might want to escape the slash in the middle of the regex ;-)
As well as some other characters, btw...
A solution for that might be to use the preg_quote function.
Here is the current working regex:
/^[\w\041\042\043\044\045\046\047\050\051\052\053\054\134\055\056\134\057\072\073\074\075\076\077\100\133\134\134\134\135\134\136\140\173\174\175\176]*$/i