Expression only finds one instance

Any questions involving matching text strings to patterns - the pattern is called a "regular expression."

Moderator: General Moderators

Post Reply
someberry
Forum Contributor
Posts: 172
Joined: Mon Apr 11, 2005 5:16 am

Expression only finds one instance

Post 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.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

post your code.

For processing nestable bbcode, I prefer to use a string-stack parser..
someberry
Forum Contributor
Posts: 172
Joined: Mon Apr 11, 2005 5:16 am

Post 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);
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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.
someberry
Forum Contributor
Posts: 172
Joined: Mon Apr 11, 2005 5:16 am

Post by someberry »

Hmm, how would I go about making a 'nesting supported parser', couldn't find anything after a quick look on Google.
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post 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..
someberry
Forum Contributor
Posts: 172
Joined: Mon Apr 11, 2005 5:16 am

Post by someberry »

Ok, thanks feyd, I was hoping I wouldn't have to loop round and manually replace them all, but ah well.

Thanks.
User avatar
Chris Corbyn
Breakbeat Nuttzer
Posts: 13098
Joined: Wed Mar 24, 2004 7:57 am
Location: Melbourne, Australia

Post 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 :?
yum-jelly
Forum Commoner
Posts: 98
Joined: Sat Oct 29, 2005 9:16 pm

Post 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
Post Reply