Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

preg_match acting very strange

I am using preg_match() to extract pieces of text from a variable, and let's say the variable looks like this:

[htmlcode]This is supposed to be displayed[/htmlcode]

middle text

[htmlcode]This is also supposed to be displayed[/htmlcode]

i want to extract the contents of the [htmlcode]'s and input them into an array. i am doing this by using preg_match().

preg_match('/\[htmlcode\]([^\"]*)\[\/htmlcode\]/ms', $text, $matches);
foreach($matches as $value){
return $value . "<br />";
}

The above code outputs

[htmlcode]This is supposed to be displayed[/htmlcode]middle text[htmlcode]This is also supposed to be displayed[/htmlcode]

instead of

  1. [htmlcode]This is supposed to be displayed[/htmlcode]
  2. [htmlcode]This is also supposed to be displayed[/htmlcode]

and if have offically run out of ideas

like image 407
Simon Andersson Avatar asked May 09 '13 23:05

Simon Andersson


4 Answers

As explained already; the * pattern is greedy. Another thing is to use preg_match_all() function. It'll return you a multi-dimension array of matched content.

preg_match_all('#\[htmlcode\]([^\"]*?)\[/htmlcode\]#ms', $text, $matches);
foreach( $matches[1] as $value ) {

And you'll get this: http://codepad.viper-7.com/z2GuSd

like image 172
hjpotter92 Avatar answered Oct 31 '22 11:10

hjpotter92


A * grouper is greedy, i.e. it will eat everything until last [/htmlcode]. Try replacing * with non-greedy *?.

like image 29
Stefano Sanfilippo Avatar answered Oct 31 '22 11:10

Stefano Sanfilippo


* is by default greedy, ([^\"]*?) (notice the added ?) should make it lazy.

  • What do lazy and greedy mean in the context of regular expressions?
like image 2
kapa Avatar answered Oct 31 '22 10:10

kapa


Look at this piece of code:

preg_match('/\[htmlcode\]([^\"]*)\[\/htmlcode\]/ms', $text, $matches);
foreach($matches as $value){
return $value . "<br />";
}

Now, if your pattern works fine and all is ok, you should know:

  • return statement will break all loops and will exit the function.
  • The first element in matches is the whole match, the whole string. In your case $text

So, what you did is returned the first big string and exited the function.

I suggest you can check for desired results:

$matches[1] and $matches[2]

like image 2
sybear Avatar answered Oct 31 '22 11:10

sybear