Warning: preg_replace(): Unknown modifier ']'

user3122995 picture user3122995 · Dec 20, 2013 · Viewed 40.3k times · Source

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?

Answer

Amal Murali picture Amal Murali · Dec 20, 2013

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:

  • When your regular expression is missing delimiters.

  • When you use the delimiter inside the pattern without escaping it.

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.

Regex: <div[^>  ]*><ul[^>]*>
       │     │  │          │
       └──┬──┘  └────┬─────┘
       pattern    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. Only imsxeADSUXJu 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:

~<div[^>]*><ul[^>]*>~
│                   │
│                   └─ ending delimiter
└───────────────────── starting delimiter

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:

/foo[^\/]+bar/i
│      │     │
└──────┼─────┴─ actual delimiters
       └─────── escaped slash(/) character

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: