2

Possible Duplicate:
Need a good regex to convert URLs to links but leave existing links alone

This is a my sample input:

http://www.website.com/1/
Click here http://www.website.com/2/ or visit the website: http://www.website.com/3/
or http://www.website.com/4/
http://www.website.com/5/

I want a PHP function that converts the URLs inside the text into tags, like so:

<a href="http://www.website.com/1/">http://www.website.com/1/</a>
Click <a href="http://www.website.com/2/">here</a> or visit the website: <a href="http://www.website.com/3/">http://www.website.com/3/</a>
or <a href="http://www.website.com/4/">http://www.website.com/4/</a>
<a href="http://www.website.com/5/">http://www.website.com/5/</a>

There is a catch on line 2: if the URL is preceded by the word here then the word should be used as the anchor text instead. I need to do this in PHP. I think preg_replace with /e switch might help me accomplish this task but I am not sure. This is the (borrowed) regex I've used so far:

preg_replace("#(^|[\n ])([\w]+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)#is", "\\1<a    href=\"\\2\" target=\"_blank\">\\2</a>", $ret);
//                     ^---- I've tried adding "|here "
//                           But I cannot get the order of \\1 and \\2 right

Please advice.

Community
  • 1
  • 1
Salman A
  • 262,204
  • 82
  • 430
  • 521

2 Answers2

1

"But I cannot get the order of \1 and \2 right"

The number of the capturing groups are in the order of the opening brackets, so the first opening bracket will always be $1. If you don't want that, use named groups.

For your problem you can try this regex

(?:(here)\s*|\b)(\w+?://[\w\#$%&~/.\-;:=,?@\[\]+]*)

It will have "here" in $1 and the link in $2. If "here" is not found then $1 is empty.

See it here on Regexr

So, then you need to replace dependent on the content of $1. If it is empty then replace the match with

<a href="$2">$2</a>

else with

<a href="$2">$1</a>

I think this should be possible using preg_replace_callback

stema
  • 90,351
  • 20
  • 107
  • 135
  • My problem was to display the word `here` -- or -- the url conditionally. As per your suggestion, `preg_replace_callback` did the job just fine! – Salman A Sep 21 '11 at 07:25
-1

I found this.

It sounds interesting, thought I have NOT tested it myself, I'm doing it now though.

The class goes like this:

class MakeItLink {
    protected function _link_www( $matches ) {
        $url = $matches[2];
        $url = MakeItLink::cleanURL( $url );
        if( empty( $url ) ) {
            return $matches[0];
        }
 
        return "{$matches[1]}<a href='{$url}'>{$url}</a>";
    }
 
    public function cleanURL( $url ) {
        if( $url == '' ) {
            return $url;
        }
 
        $url = preg_replace( "|[^a-z0-9-~+_.?#=!&amp;;,/:%@$*'()x80-xff]|i", '', $url );
        $url = str_replace( array( "%0d", "%0a" ), '', $url );
        $url = str_replace( ";//", "://", $url );
 
        /* If the URL doesn't appear to contain a scheme, we
         * presume it needs http:// appended (unless a relative
         * link starting with / or a php file).
         */
        if(
            strpos( $url, ":" ) === false
            &amp;&amp; substr( $url, 0, 1 ) != "/"
            &amp;&amp; !preg_match( "|^[a-z0-9-]+?.php|i", $url )
        ) {
            $url = "http://{$url}";
        }
 
        // Replace ampersans and single quotes
        $url = preg_replace( "|&amp;([^#])(?![a-z]{2,8};)|", "&#038;$1", $url );
        $url = str_replace( "'", "&#039;", $url );
 
        return $url;
    }
 
    public function transform( $text ) {
        $text = " {$text}";
 
        $text = preg_replace_callback(
            '#(?])(\()?([\w]+?://(?:[\w\\x80-\\xff\#$%&amp;~/\-=?@\[\](+]|[.,;:](?![\s&lt;])|(?(1)\)(?![\s&lt;])|\)))*)#is&#039;,
            array( &#039;MakeItLink&#039;, &#039;_link_www&#039; ),
            $text
        );
 
        $text = preg_replace( &#039;#(<a>]+?&gt;|&gt;))<a>]+?&gt;([^&gt;]+?)</a></a>#i', "$1$3</a>", $text );
        $text = trim( $text );
 
        return $text;
    }
}

It’s very easy to use, just load up the text you want to search for link and call the transform method:

$text = MakeItLink::transform( $text );

All of this code came out of WordPress, which is licensed under the GPL

Community
  • 1
  • 1
Trufa
  • 39,971
  • 43
  • 126
  • 190