Page 1 of 1

Expression only finds one instance

Posted: Sun Oct 30, 2005 11:36 am
by someberry
Hi,

I am currently using the regex:

Code: Select all

/\[quote\](.*?)\[\/quote\]/isU
To find quotes in BBCode, however, it only seem to find the first instance, and ignores the rest :(.

For instance:

Code: Select all

[quote]Quote #1
[quote]Quote #2[/quote][/quote]
Will execute as:

Code: Select all

Quote:
Quote #1
[quote]Quote #2[/quote]
Does anyone know of a way I could fix the problem, or a better way to do this?

Thanks,
Someberry.

Posted: Sun Oct 30, 2005 11:45 am
by feyd
post your code.

For processing nestable bbcode, I prefer to use a string-stack parser..

Posted: Sun Oct 30, 2005 12:35 pm
by someberry

Code: Select all

function quote($string){
   return preg_replace("/\[quote\](.*?)\[\/quote\]/isU", "Quote:<br />$1", $string);
}

$string = "[quote]Quote #1
[quote]Quote #2[/quote]
[/quote]";

echo quote($string);

Posted: Sun Oct 30, 2005 12:38 pm
by feyd
Using both .*? and the U pattern modifier makes .*? change to .* it's matching your entire test.

Your test will not produce the desired effect however, so you'll need to work out a nesting supported parser of some fashion like I hinted at earlier.

Posted: Sun Oct 30, 2005 12:42 pm
by someberry
Hmm, how would I go about making a 'nesting supported parser', couldn't find anything after a quick look on Google.

Posted: Sun Oct 30, 2005 12:51 pm
by feyd
basically, you find how many begin and end tags you have, then walk through them replacing (manually) as you go. The manual replacment typically involves substr() and basic string concatenation of the surrounding bits.. str_replace() can have undesired effects..

Posted: Sun Oct 30, 2005 12:55 pm
by someberry
Ok, thanks feyd, I was hoping I wouldn't have to loop round and manually replace them all, but ah well.

Thanks.

Posted: Mon Oct 31, 2005 11:41 am
by Chris Corbyn
feyd wrote:basically, you find how many begin and end tags you have, then walk through them replacing (manually) as you go. The manual replacment typically involves substr() and basic string concatenation of the surrounding bits.. str_replace() can have undesired effects..
It would perhaps be easier to tokenize the string using a regex (break it into chunks) whereby the BBCode tags stay in tact so that you can walk through the tokens and keep a count as you do so. You can then walk through the tokens again, proccessing the data. I'm about to start writing a custom BBCode parser and that's kinda what I had in mind, although mine needs to do fancier things using optional attributes in the tags too :?

Posted: Mon Oct 31, 2005 7:19 pm
by yum-jelly
If you just want a simple loop example here one is...

This works by getting first opening tag to the last closing tag, it does the same thing until it does not find a match!

Code: Select all

<?php

function quote ( $string )
{
	$old = array ( '#\\[quote=\'?"?`?\b(.*)\b\'?"?`?\\](.*)\\[\\/quote\\]#Uis', '#\\[quote\\](.*)\\[\/quote\\]#Uis' );
	$new = array ( '<br />Quote By: \\1<br />\\2', '<br />Quote:<br />\\1' );

	while ( preg_match ( '!\[quote.*\].*\[/quote\]!Uis', $string ) )
	{
		$string = preg_replace ( $old, $new, $string );
	}

	// any extra uneven tags could be killed here

	/* $string = preg_replace ( "#\[/?quote.*\]#i", "", $string ); */

	return ( $string ); 
} 

$string = "[quote]Quote #1 
[quote='tiny_tim']other quote
[quote]Quote #2[/quote] 
[/quote][/quote]"; 

echo quote ( $string ); 


?>

yj