Regular expression error: no ending delimiter - php

I'm trying to execute this regular expression:
<?php
preg_match("/^([^\x00-\x1F]+?){0,1}/", 'test string');
?>
But keep getting an error:
Warning: preg_match() [function.preg-match]: No ending delimiter '/' found in /var/www/preg.php on line 6
I can't understand where it is coming from. I have an ending delimeter right there... I tried to change delimiter to other symbols and it didn't help.
I would appreciate your help on this problem.

I guess PHP chokes on the NULL character that denotes the end of a string in C.
Try it with single quotes so that \x00 is interpreted by the PCRE engine and not by PHP:
'/^([^\x00-\x1F]+?){0,1}/'
It seems that this is an already known bug (see Problems with strings containing \x00).

Like Gumbo said, preg_match is not binary safe.
Use instead:
preg_match("/^([^\\x{00}-\\x{1F}]+?){0,1}/", 'test string'));
This is the correct way to specify Unicode code points in PCRE.

I am not sure about php, but maybe the problem is that you need to escape your backslashes?
try "/^([^\\x00-\\x1F]+?){0,1}/"

Related

Escaping regular expressions in PHP

I am trying to escape a PCRE in PHP for use in a script. For some reason I can't get it to function when it has been escaped, I've only managed to get it working when the REGEX is given as a form input.
The Regex I'm using is:
$pattern = '£((http|ftp|https):\/\/)?([\w\-_]+(?:(?:\.[\w\-_]+)+))([\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#])?£';
So far I have tried:
preg_quote(): converts the Regex to the following and throws an error: £((http\|ftp\|https):\/\/)\?([\w\-_]+(\?:(\?:\.[\w\-_]+)+))([\w\-\.,#\?\^\=%&:/~\+#]*[\w\-\#\?\^\=%&/~\+#])\?£
htmlentities(): gives error: Warning: preg_match(): Unknown modifier 'a'
addslashes(): same as above
mixture of the 3: same as above
Does anyone have an idea of what I'm doing wrong?
The pound symbol was the issue here, replacing it to an exclamation mark solved the problem.
Working expression:
$pattern = '!((http|ftp|https):\/\/)?([\w\-_]+(?:(?:\.[\w\-_]+)+))([\w\-\.,#?^=%&:/~\+#]*[\w\-\#?^=%&/~\+#])?!';
For some reason this is working fine with no escape functions.

Symfony2 url validation : "preg_match(): Compilation failed: range out of order in character class" [duplicate]

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.

Can't get Regex working in PHP, works in RegEXP program

Here is the input I am searching:
\u003cspan class=\"prs\">email_address#me.com\u003c\/span>
Trying to just return email_address#me.com.
My regex class=\\"prs\\">(.*?)\\ returns "class=\"prs\">email_address#me.com\" in RegExp which is OK, I can work with that result.
But I can't get it to work in PHP.
$regex = "/class=\\\"prs\\\">(.*?)\\/";
Gives me an error "No ending delimiter"
Can someone please help?
Your original code:
$regex = "/class=\\\"prs\\\">(.*?)\\/";
The reason you get No ending delimiter is that although you are escaping the backslash prior to the closing forward slash, what you have done is escaped it in the context of the PHP string, not in the context of the regex engine.
So the PHP string escaping mechanism does its thing, and by the time the regex engine gets it, it will look like this:
/class=\"prs\">(.*?)\/
This means that the regular expression engine will see the backslash at the end of the expression as escaping the forward slash that you are intending to use to close the expression.
The usual PHP solution to this kind of thing is to switch to using single-quoted string instead of a double-quoted one, but this still won't work, as \\ is an escaped backslash in both single and double quoted strings.
What you need to do is double up the number of backslash characters at the end of your string, so your code needs to look like this:
$regex = "/class=\\\"prs\\\">(.*?)\\\\/";
The way to prove what it's doing is to print the contents of the $regex variable, so you can see what the string will look like to the regex engine. These kinds of errors are actually very hard to spot, but looking at the actual content of the string will help you spot them.
Hope that helps.
If you change to single quotes it should fix it
$regex = '/class=\\\"prs\\\">(.*?)\\/';

Range out of order in character class

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.

Weird error using preg_match and unicode

if (preg_match('(\p{Nd}{4}/\p{Nd}{2}/\p{Nd}{2}/\p{L}+)', '2010/02/14/this-is-something'))
{
// do stuff
}
The above code works. However this one doesn't.
if (preg_match('/\p{Nd}{4}/\p{Nd}{2}/\p{Nd}{2}/\p{L}+/u', '2010/02/14/this-is-something'))
{
// do stuff
}
Maybe someone could shed some light as to why the one below doesn't work. This is the error that is being produced:
A PHP Error was encountered
Severity: Warning
Message: preg_match()
[function.preg-match]: Unknown
modifier '\'
Try this: (delimit the regex with ())
if (preg_match('#\p{Nd}{4}/\p{Nd}{2}/\p{Nd}{2}/\p{L}+#', '2010/02/14/this-is-something'))
{
// do stuff
}
Edited
The modifier u is available from PHP 4.1.0 or greater on Unix and from PHP 4.2.3 on win32.
Also as nvl observed, you are using / as the delimiter and you are not escaping the / present in the regex. So you'lll have to use:
/\p{Nd}{4}\/\p{Nd}{2}\/\p{Nd}{2}\/\p{L}+/u
To avoid this escaping you can use a different set of delimiters like:
#\p{Nd}{4}/\p{Nd}{2}/\p{Nd}{2}/\p{L}+#
or
#\p{Nd}{4}/\p{Nd}{2}/\p{Nd}{2}/\p{L}+#
As a tip, if your delimiter is present in your regex, its better to choose a different delimiter not found in the regex. This keeps the regex clean and short.
In the second regex you're using / as the regex delimiter, but you're also using it in the regex. The compiler is trying to interpret this part as a complete regex:
/\p{Nd}{4}/
It thinks the next character after the second / should be a modifier like 'u' or 'm', but it sees a backslash instead, so it throws that cryptic exception.
In the first regex you're using parentheses as regex delimiters; if you wanted to add the u modifier, you would put it after the closing paren:
'(\p{Nd}{4}/\p{Nd}{2}/\p{Nd}{2}/\p{L}+)u'
Although it's legal to use parentheses or other bracketing characters ({}, [], <>) as regex delimiters, it's not a good idea IMO. Most people prefer to use one of the less common punctuation characters. For example:
'~\p{Nd}{4}/\p{Nd}{2}/\p{Nd}{2}/\p{L}+~u'
'%\p{Nd}{4}/\p{Nd}{2}/\p{Nd}{2}/\p{L}+%u'
Of course, you could also escape the slashes in the regex with backslashes, but why bother?

Categories