views:

137

answers:

4

Hey Guys,

i'm not very firm with preg_replace - in other Words i do not really understand - so i hope you can help me.

I have a string in a Text like this one: [demo category=1] and want to replace with the Content of Category (id=1) e.g. "This is the Content of my first Category"

This is my startpoint Pattern - that's all i have: '/[demo\s*.*?]/i';

Hope you can help?

Thanks, Sascha

A: 

The pattern is going to be like this

/\[demo\s+category=(\d+)\]/i'

(you need to escape brackets because they're special)

stereofrog
A: 

The [ and ] characters have special meaning (they denote character classes - ranges and collections of character). You need to escape [ as \[ (and evidently in PHP, unlike other regex flavors, you also need to escape ]). Also I suggest you make use of the character class [^]] = match any character that is not a ]

/\[demo\s+[^]]*\]/i

should work better.

Edit: If you want to extract the name and number, then you can use

/\[demo\s+(\w+)\s*=\s*(\d+)\]/i
Tim Pietzcker
You need to escape ]. ;)
stereofrog
Huh. Indeed RegexBuddy suggests this. It does so, too, for other flavors where it's definitely not necessary (like Python). I think RegexBuddy is overly cautious here. I haven't tried it with PHP - sure it doesn't work when `]` is not escaped?
Tim Pietzcker
It does work, but still should be escaped for readability reasons.
stereofrog
Hm. I find it helps readability to avoid unnecessary backslashes whenever possible. Interestingly, Jan Goyvaerts has blogged about this problem: http://www.regexguru.com/2008/12/dont-escape-literal-characters-that-arent-metacharacters/
Tim Pietzcker
...and here: http://www.regexguru.com/2008/04/escape-characters-only-when-necessary/ - in that case he advocates escaping the closing `]`. Matter of taste, in the end...
Tim Pietzcker
+1  A: 

Firstly, you need to escape the square brackets as they are special characters in PCREs:

'/\[demo\s*.*?\]/i';

Secondly, it sounds like you want to do something with the digit at the end, so you'll want to capture it using parenthesis:

'/\[demo\s*.*?=(\d+)\]/i';

The braces will capture \d+ and store it in a reference. \d+ will match a string of numbers only.

Finally, it sounds like you need to use preg_replace_callback to perform a special function on the matches in order to get the string you want:

function replaceMyStr($matches)
{
    $strNum = array("1"=>"first", "2"=>"second", "3"=>"third"); // ...etc
    return "This is the Content of my ".$strNum($matches[1])." Category.";
    // $matches[1] will contain the captured number
}
preg_replace_callback('/\[demo\s*.*?=(\d+)\]/i', "replaceMyStr", "[demo category=1]");
Andy E
+1  A: 

further to the above answers, you have 2 ways to do the actual replacing. assuming you have 10 category names you want to replace, you can either do something like

for ($i = 1; $i <= $max_category; $i++) {
 $category_name = get_category_name($i);
 $s = preg_replace("/\[demo\s+category=(\d+)\]/i", $category_name, $s);
}

or

$s = preg_replace_callback("/\[demo\s+category=(\d+)\]/i", "get_category_name", $s);

in both cases, get_category_name($id) is a function that will get a category name for an id. you should test both options to evaluate which is faster for your uses.

oedo