I have the following error:
Warning: preg_replace(): Unknown modifier ‘]’ in xxx.php on line 38
This is the code on line 38:
<?php echo str_replace("</ul></div>", "", preg_replace("<div[^>]*><ul[^>]*>", "", wp_nav_menu(array('theme_location' => 'nav', 'echo' => false)) )); ?>
How can I fix this problem?
Why the error occurs
In PHP, a regular expression needs to be enclosed within a pair of delimiters. A delimiter can be any non-alphanumeric, non-backslash, non-whitespace character;
/
,#
,~
are the most commonly used ones. Note that it is also possible to use bracket style delimiters where the opening and closing brackets are the starting and ending delimiter, i.e.<pattern_goes_here>
,[pattern_goes_here]
etc. are all valid.The “Unknown modifier X” error usually occurs in the following two cases:
In this case, the regular expression is
<div[^>]*><ul[^>]*>
. The regex engine considers everything from<
to>
as the regex pattern, and everything afterwards as modifiers.]
here is an unknown modifier, because it appears after the closing>
delimiter. Which is why PHP throws that error.Depending on the pattern, the unknown modifier complaint might as well have been about
*
,+
,p
,/
or)
or almost any other letter/symbol. OnlyimsxeADSUXJu
are valid PCRE modifiers.How to fix it
The fix is easy. Just wrap your regex pattern with any valid delimiters. In this case, you could chose ~ and get the following:
If you’re receiving this error despite having used a delimiter, it might be because the pattern itself contains unescaped occurrences of the said delimiter.
Or escape delimiters
/foo[^/]+bar/i
would certainly throw an error. So you can escape it using a backslash if it appears anywhere within the regex:This is a tedious job if your regex pattern contains so many occurrences of the delimiter character.
The cleaner way, of course, would be to use a different delimiter altogether. Ideally a character that does not appear anywhere inside the regex pattern, say
#
–#foo[^/]+bar#i
.More reading:
preg_quote()
)Other examples
The reference answer already explains the reason for “Unknown modifier” warnings. This is just a comparison of other typical variants.
When forgetting to add regex
/
delimiters/
, the first non-letter symbol will be assumed to be one. Therefore the warning is often about what follows a grouping(â¦)
,[â¦]
meta symbol:Sometimes your regex already uses a custom delimiter (
:
here), but still contains the same character as unescaped literal. It’s then mistaken as premature delimiter. Which is why the very next symbol receives the “Unknown modifier â” trophy:When using the classic
/
delimiter, take care to not have it within the regex literally. This most frequently happens when trying to match unescaped filenames:Or when matching angle/square bracket style tags:
Templating-style (Smarty or BBCode) regex patterns often require
{â¦}
or[â¦]
brackets. Both should usually be escaped. (An outermost{}
pair being the exception though).They also get misinterpreted as paired delimiters when no actual delimiter is used. If they’re then also used as literal character within, then that’s, of course ⦠an error.
Whenever the warning says “Delimiter must not be alphanumeric or backslash” then you also entirely forgot delimiters:
“Unkown modifier ‘g’” often indicates a regex that was copied verbatimly from JavaScript or Perl.
PHP doesn’t use the
/g
global flag. Instead thepreg_replace
function works on all occurences, andpreg_match_all
is the “global” searching pendant to the one-occurencepreg_match
.So, just remove the
/g
flag.See also:
· Warning: preg_replace(): Unknown modifier ‘g’
· preg_replace: bad regex == ‘Unknown Modifier’?
A more peculiar case pertains the PCRE_EXTENDED
/x
flag. This is often (or should be) used for making regexps more lofty and readable.This allows to use inline
#
comments. PHP implements the regex delimiters atop PCRE. But it doesn’t treat#
in any special way. Which is how a literal delimiter in a#
comment can become an error:(Also noteworthy that using
#
as#abc+#x
delimiter can be doubly inadvisable.)Interpolating variables into a regex requires them to be pre-escaped, or be valid regexps themselves. You can’t tell beforehand if this is gonna work:
It’s best to apply
$var = preg_quote($var, "/")
in such cases.See also:
· Unknown modifier ‘/’ in …? what is it?
Another alternative is using
Qâ¦E
escapes for unquoted literal strings:Note that this is merely a convenience shortcut for meta symbols, not dependable/safe. It would fall apart in case that
$var
contained a literal'E'
itself (however unlikely). And it does not mask the delimiter itself.Deprecated modifier /e is an entirely different problem. This has nothing to do with delimiters, but the implicit expression interpretation mode being phased out. See also: Replace deprecated preg_replace /e with preg_replace_callback
Alternative regex delimiters
As mentioned already, the quickest solution to this error is just picking a distinct delimiter. Any non-letter symbol can be used. Visually distinctive ones are often preferred:
~abc+~
!abc+!
@abc+@
#abc+#
=abc+=
%abc+%
Technically you could use
$abc$
or|abc|
for delimiters. However, it’s best to avoid symbols that serve as regex meta characters themselves.The hash
#
as delimiter is rather popular too. But care should be taken in combination with thex
/PCRE_EXTENDED
readability modifier. You can’t use# inline
or(?#â¦)
comments then, because those would be confused as delimiters.Quote-only delimiters
Occassionally you see
"
and'
used as regex delimiters paired with their conterpart as PHP string enclosure:Which is perfectly valid as far as PHP is concerned. It’s sometimes convenient and unobtrusive, but not always legible in IDEs and editors.
Paired delimiters
An interesting variation are paired delimiters. Instead of using the same symbol on both ends of a regex, you can use any
<...>
(...)
[...]
{...}
bracket/braces combination.While most of them also serve as regex meta characters, you can often use them without further effort. As long as those specific braces/parens within the regex are paired or escaped correctly, these variants are quite readable.
Fancy regex delimiters
A somewhat lazy trick (which is not endorsed hereby) is using non-printable ASCII characters as delimiters. This works easily in PHP by using double quotes for the regex string, and octal escapes for delimiters:
The