Viewed   515 times

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?

 Answers

1

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:

  • PHP regex delimiters
  • http://www.regular-expressions.info/php.html
  • How can I convert ereg expressions to preg in PHP? (missing delimiters)
  • Unknown modifier '/' in …? what is it? (on using preg_quote())
Tuesday, August 2, 2022
4

Your string contains a whole mess of / which would need to be escaped as / when using / as the regex delimiter. Instead of / as the regex delimiters, use something which won't occur in your string like ~ for example. You must choose a delimiting character which is guaranteed not to appear in $Src, however. You might be safer even with | than with ~.

$Src = 'images/pages/clients/logos/clnt_aljareera_img.jpg';
// Delimit the regular expression with ~
$pttn= '~&Src:'.$Src.'~';
$string=preg_replace($pttn,'',$string,1);

What has happened is your regex delimited by / encounters a p immediately after images/ because it thinks it has reached the closing delimiter. The next word pages is mistakenly treated as a string of regex modifiers.

PHP sees the regular expression:

/&src:images/pages
Tuesday, August 2, 2022
 
4

Okay I will answer my own questions:

  1. Yes it is normal that there are no <p> on get_the_content() thanks @s_ha_dum
  2. To add the <p> I need to apply the content filter as mentioned here (scroll down to "Alternative Usage").
  3. The regex is not wrong but it is pretty dirty to regex the html. Thanks @MarcB

See the new question that lead to the following code here

$dom = new DOMDocument;
$dom->loadHTML(get_the_content());
$xpath = new DOMXPath($dom);
$nodes = $xpath->query('//img|//a[img]');
foreach($nodes as $node) {
    $node->parentNode->removeChild($node);
}
$no_image_content = $dom->saveHTML();
$no_image_content = apply_filters('the_content', $no_image_content);
$no_image_content = str_replace(']]>', ']]&gt;', $no_image_content);
echo $no_image_content;
Friday, August 19, 2022
 
3
$content = <<<HTML
<h1 class="heading-title">test1</h1>
<H2 class="green">test2</H2>
<h5 class="red">test</h5>
<h5 class="">test test</h5>
HTML;

$content = preg_replace('#<h([1-6]).*?class="(.*?)".*?>(.*?)</h[1-6]>#si', '<p class="heading-${1} ${2}">${3}</p>', $content);

echo htmlentities($content);

Result:

<p class="heading-1 heading-title">test1</p> 
<p class="heading-2 green">test2</p> 
<p class="heading-5 red">test</p> 
<p class="heading-5 ">test test</p>

Note for existing classes: Even if your element doesn't have an existing class you have to add empty class attribute class="". Instead this will not work as expected. :( Better solution is to use preg_replace_callback. Then you can check if a match exists and create your p tags more accurately.

Wednesday, September 21, 2022
 
jeevan
 
5

Your regex will break if the string $id_base has a / in it as you are using / as the regex delimiter.

To fix this use preg_quote on $id_base as:

if (preg_match('/'. preg_quote($id_base,'/').'-([0-9]+)$/', .....) {
Saturday, October 29, 2022
 
shilly
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :