views:

284

answers:

4

LS,

I'm using the following code to add <span> tags behind <a> tags.

$html = preg_replace("~<a.*?href=\"$url\".*?>.*?</a>~i", "$0<span>test</span>", $html);

The code is working fine for regular links (ie. http://www.google.com/), but it will not perform a replace when the contents of $url are $link$/3/.

This is example code to show the (mis)behaviour:

<?php
    $urls = array();
    $urls[] = '$link$/3/';
    $urls[] = 'http://www.google.com/';

    $html = '<a href="$link/3/">Test Link</a>' . "\n" . '<a href="http://www.google.com/"&gt;Google&lt;/a&gt;';

    foreach($urls as $url) {
        $html = preg_replace("~<a.*?href=\"$url\".*?>.*?</a>~i", "$0<span>test</span>", $html);
    }

    echo $html;
?>

And this is the output it produces:

<a href="$link$/3/">Test Link</a>
<a href="http://www.google.com/"&gt;Google&lt;/a&gt;&lt;span&gt;test&lt;/span&gt;

Kind regards,

Matthias Vance

+3  A: 

$url = preg_quote($url, '~'); the dollar signs are interpreted as usual: end-of-input.

just somebody
D'oh. I totally that my dollar signs would match EOL/EOI. I will escape them to avoid this issue. Thank you for the quick reply!
Matthias Vance
A: 

$ has special meaning in regex. End of line. Your expression is being expanded like this:

$html = preg_replace("~<a.*?href=\"$link$/3/\".*?>.*?</a>~i", "$0<span>test</span>", $html);

Which fails because it can't find "link" between two end of lines. Try escaping the $ in the $urls array:

$urls[] = '\$link\$/3/';
Mark Moline
+1  A: 

$ is considered a special regex character and needs to be escaped. Use preg_quote() to escape $url before passing it to preg_replace().

$url = preg_quote($url, '~');
Jordan Ryan Moore
+2  A: 

just somebody is correct; you must escape your special regex characters if you mean for them to be interpreted as literal.

It also looks to me like it can't perform the replace because it never makes a match.

Try replacing this line:

$urls[] = '$link$/3/';

With this:

$urls[] = '$link/3/';
Mikuso
+1 this change is needed as well.
gameover
That's impossible because that's the dynamic input my script is getting. I just made it static to show where it fails.
Matthias Vance
Do you mean to say that $link should refer to a variable?In that case, you must either concatenate the $link variable to `'/3/'` or enclose the whole thing in double quotes instead of single. `$urls[] = "$link/3/";`
Mikuso
I meant to say that that line is 100% correct. That is the data I'm getting from the database. I just used single quotes to demonstrate it. I got it working perfectly now using preg_quote().
Matthias Vance