JimmyBanks
JimmyBanks

Reputation: 4718

RegEx to remove bbcode tag nested within bbcode tag

I need to prepare a regular expression that can be used to remove a bbcode [QUOTE] (examples: [QUOTE=name]; [QUOTE=123;123]) tag, when it is nested within a pre-existing [QUOTE] tag.

The current regular expression I am using is from the answer here (full explanation of the regex included): Remove nested quotes

~\G(?!\A)(?>(\[quote\b[^]]*](?>[^[]+|\[(?!/?quote)|(?1))*\[/quote])|(?<!\[)(?>[^[]+|\[(?!/?quote))+\K)|\[quote\b[^]]*]\K~

However, this only removes a second or later nested [QUOTE] tag, but leaves a single nested tag, I now want to have all [QUOTE] tags removed if they are nested within an existing [QUOTE] tag.

An example of an input and how it should output from preg_replace():

//input
$string = 'Here is a quote [QUOTE=person]I am also quoting [QUOTE]this is a nested quote[/QUOTE][/QUOTE]';

//preg replace
$string = preg_replace('regular_expression', '', $string);

//output
echo $string;
// Here is a quote [QUOTE=person]I am also quoting[/QUOTE]

Upvotes: 2

Views: 285

Answers (1)

Jan
Jan

Reputation: 43169

You could use a recursive approach:

(\[QUOTE[^][]*\])
(
    (?:[^][]+|(?R))+
)
\[/QUOTE\]

See a demo on regex101.com.


In PHP this would be:
$regex = '~
        (\[QUOTE[^][]*\])
        (
            (?:[^][]+|(?R))+
        )
        (\[/QUOTE\])
        ~x';

$string = 'Here is a quote [QUOTE=person]I am also quoting [QUOTE]this is a nested quote[/QUOTE][/QUOTE]';

$string = preg_replace_callback($regex, 
    function($match) {
        return $match[1] . preg_replace('~\[/?[^][]*\]~', '', $match[2]) . $match[3];
    },
    $string);

echo $string;
?>


This yields

Here is a quote [QUOTE=person]I am also quoting this is a nested quote[/QUOTE]

Upvotes: 0

Related Questions