user1670459
user1670459

Reputation: 3

preg_replace returns unexpected results to $1

<?php
$data='123
[test=abc]cba[/test]
321';
$test = preg_replace("(\[test=(.+?)\](.+?)\[\/test\])is","$1",$data);
echo $test;
?>

I expect the above code to return abc but instead of returning abc it returns 123 abc 321 Please tell me what I am doing wrong.

Upvotes: 0

Views: 231

Answers (3)

Alan Moore
Alan Moore

Reputation: 75232

I don't know if you're aware of this, but the outermost set of parentheses in your regex does not form a group (capturing or otherwise). PHP is interpreting them as regex delimiters. If you are aware of that, and you're using them as delimiters on purpose, please don't. It's usually best to use a non-bracketing character that never has any special meaning in regexes (~, %, @, etc.).

I agree with Casimir that preg_match() is the tool you should be using, not preg_replace(). But his solution is trickier than it needs to be. Your original regex works fine; all you have to do is grab the contents of the first capturing group, like so:

if (preg_match('%\[test=(.+?)\](.+?)\[/test\]%si', $data, $match)) {
    $test = $match[1];
}

Upvotes: 1

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89557

You don't need to use a replace here, all that you need is to take something in the string. To do that preg_match is more useful:

$data='123
[test=abc]cba[/test]
321';
$test = preg_match('~\[test=\K[^\]]++~', $data, $match);
echo $match[0];

Upvotes: 0

Paul Roub
Paul Roub

Reputation: 36438

You're only replacing the matched part (the BBcode section). You're leaving the rest of the string untouched.

If you also want to remove the leading/trailing text, include those in the expression:

$test = preg_replace("(.*\[test=(.+?)\](.+?)\[\/test\].*)is","$1",$data);

Upvotes: 1

Related Questions