nitotm
nitotm

Reputation: 579

Repeated match inside match

   $regex = '/\[b\](.*?)\[\/b\]/is';

   $string = '[b][b][b]string[/b][/b][/b]';

This will only match until the first [/b], so if I use this regex to convert this bbcode to HTML I will end up with this:

string[/b][/b]

I'm using PHP preg_replace, how I can end up with just string, so 3 html bold tags.

Upvotes: 1

Views: 95

Answers (2)

revo
revo

Reputation: 48711

For such dirty cases:

this [b]is [b]a[/b][/b] test [b]string[/b]

A recursive solution works:

\[b](?:(?:(?!\[b]).)*?|(?R))*\[/b]

Live demo

PHP code:

$str = 'this [b]is [b]a[/b][/b] test [b]string[/b]';

echo preg_replace_callback('~\[(\w+)](?:(?:(?!\[\1]).)*?|(?R))*\[/(\1)]~', function($m) {
    return "**".preg_replace("~\[/?$m[1]]~", '', $m[0])."**";
}, $str);

Outputs:

this **is a** test **string**

Upvotes: 3

Thomas Ayoub
Thomas Ayoub

Reputation: 29431

You can use a non-capture group to extend the repetition count:

(?:\[b\])+(.*?)(?:\[\/b\])+
^^^     ^^     ^^^       ^^

See demo

Upvotes: 1

Related Questions