php Regex never my strong side :P

Hi All,

I want to create a custom tag for a site and i need some regex to work through the parameters.

let's say that i've got a string that holds a bunch of text / html and also contains this tag
[customtag type="test" width="120" height="233"]

I would like to end up with
$customtag as an array
$customtag['type'] = 'test'
$customtag['width'] = 120
etc.

here's what i got so far:

$pattern = '#\\[customtag([^\]]+)\]#smi';
preg_match_all($pattern, $content, $matches);

echo $matches; 

but how do I pregmatch the matches to get the different attributes out in an array? 


 

Open in new window


LVL 13
p_nutsAsked:
Who is Participating?
 
Ray PaseurCommented:
Given the test data, this works.  But note that your output from this is highly dependent on the test data.  Try deleting the second $str and running it with a more comprehensive set of test data and you will see what I mean.
http://www.laprbass.com/RAY_temp_pnuts.php

You might want to consider what will happen if you have more than one of these tags.  Just a thought, ~Ray
<?php // RAY_temp_pnuts.php
error_reporting(E_ALL);
echo "<pre>";

// TEST DATA
$str = 'html stuff [customtag type="test" width="120"  height="233"] more html stuff [customtag type="test" width="240"  height="1"] html stuff [othertag type="work" width="120"  ] more html stuff.';
$str = 'html stuff [customtag type="test" width="120"  height="233"] more html stuff.';
var_dump($str);

// A REGEX TO FIND ALL THE BRACKETED STRINGS
$rgx
= '#'        // REGEX DELIMITER
. '\['       // ESCAPED BRACKET
. '(.*?)'    // GROUP OF ANYTHING UNGREEDY
. '\]'       // ESCAPED BRACKET
. '#'        // REGEX DELIMITER
;

preg_match_all($rgx, $str, $mat);

$out = array();
foreach ($mat[1] as $str)
{
    // REMOVE THE NOISE
    $str = str_replace('"', NULL, $str);
    $str = str_replace("'", NULL, $str);
    $str = preg_replace('#\s\s+#', ' ', $str);
    $str = trim($str);

    // BREAK THE TAG APART
    $arr = explode(' ', $str);
    $ndx = $arr[0];
    unset($arr[0]);
    $out[$ndx] = array();

    // EXTRACT EACH KEY-VALUE PAIR
    foreach ($arr as $kvp)
    {
        $knp = explode('=', $kvp);
        $out[$ndx][$knp[0]] = $knp[1];
    }

}
var_dump($out);

Open in new window

0
 
Scott MadeiraCommented:
I wouldn't use regular expressions once I go to this point.  I'd use standard PHP functions to get what you need.


 
<?php

// Break string into pieces where there is a space
$matchlist = explode(' ',$matches);

// Loop through each segment of the matchlist
foreach ($matchlist as $value){
     
    // if the value is not customtag then split it at the = sign
    // You may have to strip off the quotes if you don't want them as part of the string 
    if ($value != 'customtag'){
    	$attr = explode('=', $value);
    	$customtag[$attr[0] = $attr[1];    	
    }

}


?>

Open in new window

0
 
Scott MadeiraCommented:
Note: line 13 is missing a closing bracket ']'  Should be:  

$customtag[$attr[0]] = $attr[1];
0
Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

 
ChrissalterCommented:
Havent done php for a while but a really good resource for regex is

http://www.txt2re.com

Creates the code for you :0)
0
 
Lukasz ChmielewskiCommented:
Take a look at this example:

<?php
	$file = '[customtag type="test" width="120" height="233"]';
	preg_match("/\[customtag type=\"([^\"]+)\" width=\"([^\"]+)\" height=\"([^\"]+)\"\]/", $file, $matches);
	print_r($matches);
?>

Open in new window


The array holds the parameters you want.
0
 
Lukasz ChmielewskiCommented:
You may find this link accurate for your needs in the future:
http://gskinner.com/RegExr/
0
 
p_nutsAuthor Commented:
hi Roads_Road

i like your example but I want to make it so that the attributes are optional.

how would you do that?
0
 
p_nutsAuthor Commented:
also what if a user changes the order of the attributes
0
 
Lukasz ChmielewskiCommented:
That requires a more complex regex - can you post an example of few ones you want to include ?
0
 
p_nutsAuthor Commented:
$file = 'html stuff [customtag type="test" width="120"  height="233"] more html stuff.';

that's it.

0
 
p_nutsAuthor Commented:
where type is always needed.. width and height are optional .. and i would like this to be as flexible as possible so the order shouldn't matter.
0
 
p_nutsAuthor Commented:
wouldn't that just be a case of adjusting the regex pattern to match the type?

0
 
Terry WoodsIT GuruCommented:
Ray's code looks pretty good to me, so I won't even try creating my own solution. Post another comment if you get stuck though.
0
 
Ray PaseurCommented:
just be a case of adjusting the regex pattern -- No, I think it would be more a case of adjusting the entire design pattern.  There are three numbers that matter in computer programming: zero, one and infinity.  Your question and test case works well for one.  It fails for more than one if there is any duplication of a tag in the input string.  This is not a regex question, it is a data and design question.

If you want to post a new question and include a larger test data set, you might find more interesting solutions to this issue.  But if the test data posted at ID:37309318 is all we have, then the question is completely answered.

Best regards, ~Ray
0
 
Scott MadeiraCommented:
I'll go back to my original question / idea in post ID 37308486.  Why do you want to solve this problem with a RegEx?  

As you have seen from the other posts, the regex method is not trivial and may not be possible if the parameters in your data change.

0
 
p_nutsAuthor Commented:
hi ray. et all..

the multiple issue was actually a quick fix. as i replace the content i just did a preg_replace and limit it to 1 so it would only do the actual customtag that it was working on.

so it's time for points..

thanks all!

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.