Regular Expression (preg_replace) help

I have the following regular expression…

 '/\\[img float\\=left width\\=(.*?) height\\=(.*?)\\](.*?)\\[\\/img\\]/i', 

This checks for BBCode to float an image.

How can I make it match no mater where width or height are in the first BBCode image tag?

For example:

[img float=left width=8 height=5]http://exmaple.com/image.png[/img]

would match

but

[img float=left height=5 width=8]http://exmaple.com/image.png[/img]

would also match.

Thanks!

Thanks, you’ve not done too bad yourself either! :smiley:

You could theoretically do that in one expression with a lot of alternative, but I strongly advise against that as it would be very hard to read and a major PITA to maintain.

Instead, I’d do something like this:


$post='[img float=center width=10 height=20]test.gif[/img]';

$src=$float='';
$width=$height=0;
if (preg_match('~\\[img([^\\]]*)\\]([^\\]]*)\\[\\/img\\]~i', $post, $matches)) {
  $src=$matches[2];
  if (strlen($matches[0])) {
   $attribs=$matches[0];
   if (preg_match('~width=(\\d*)~i', $attribs, $matches)) {
     $width=$matches[1];
   }
   if (preg_match('~height=(\\d*)~i', $attribs, $matches)) {
     $height=$matches[1];
   }
   if (preg_match('~float=(left|center|right)~i', $attribs, $matches)) {
     $float=$matches[1];
   }
 }
}

var_dump($src);
var_dump($width);
var_dump($height);
var_dump($float);

:slight_smile:

NB: This will match at most one image in the post. If people are allowed multiple images, take a look at [fphp]preg_match_all[/fphp]

Thanks! That’s awesome :smiley: :D! I don’t really understand the expression though. Do you know a good place I could learn?

Not the best I admit.


<?php
function parse_bb_img($bb){
  
  $tag = array(
    'content'     => '',
    'attributes'  => array()
  );
  
  preg_match(
    '~(?<=\\[img)([^\\]]+)](.+)(?=\\[/img\\])~i',
    $bb,
    $match
  );
  
  if(3 !== count($match)){
    return $tag;
  }
  
  $tag['content'] = $match[2];
  
  $attrib = array();
  
  preg_match_all('~(\\w+)=(\\w+)~', $match[1], $attrib);
  
  for($i = 0; $i < count($attrib); $i++){
    $tag['attributes'][$attrib[1][$i]] = $attrib[2][$i];
  }
  
  return $tag;
}

print_r(
  parse_bb_img('[img float=center width=10 height=20]test.gif[/img]')
);

/*
Array
(
    [content] => test.gif
    [attributes] => Array
        (
            [float] => center
            [width] => 10
            [height] => 20
        )
)
*/

Not the best? That’s awesome! Mind if i take it one step further though?

replace


function parse_bb_img($bb){

with


function parse_bb($bb, $tag){

and


'~(?<=\\[img)([^\\]]+)](.+)(?=\\[/img\\])~i',

with


'~(?<=\\['.$tag.')([^\\]]+)](.+)(?=\\[/'.$tag.'\\])~i',

and lastly replace


$tag = array(
    'content'     => '',
    'attributes'  => array()
  );

with


$tag = array(
    'input'     => '',
    'content'     => '',
    'attributes'  => array()
  );

and below $tag['content'] = $match[2]; add:


$tag['input'] = $match[0];

and you’ve got yourself a generic bb parser!


$images=parse_bb($code, 'img');
$replace=array();
foreach($images as $image) {
  $newImage= // do whatever you want to convert the image to html using $image['content'] and $image['attributes']
  $replace[ $image['input'] ]=$newImage;
}
$post=str_replace(array_keys($replace), array_values($replace), $post);

:smiley:

Okay, not quite, since it can only take on of each tag (which is also why my last snippet won’t work at the moment), but it’s rather trivial to extend that to multiple using [fphp]preg_replace_all[/fphp] instead of preg_replace.

@kaamaru A nice place to start learning regex is at http://www.regular-expressions.info/