7

I've created this regex

(www|http://)[^ ]+

that match every http://... or www.... but I dont know how to make preg_replace that would work, I've tried

preg_replace('/((www|http://)[^ ]+)/', '<a href="\1">\1</a>', $str);

but it doesn't work, the result is empty string.

Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
Jakub Arnold
  • 85,596
  • 89
  • 230
  • 327

6 Answers6

14

You need to escape the slashes in the regex because you are using slashes as the delimiter. You could also use another symbol as the delimiter.

// escaped
preg_replace('/((www|http:\/\/)[^ ]+)/', '<a href="\1">\1</a>', $str);

// another delimiter, '@'
preg_replace('@((www|http://)[^ ]+)@', '<a href="\1">\1</a>', $str);
Paige Ruten
  • 172,675
  • 36
  • 177
  • 197
2

When using the regex codes provided by the other users, be sure to add the "i" flag to enable case-insensitivity, so it'll work with both HTTP:// and http://. For example, using chaos's code:

preg_replace('!(www|http://[^ ]+)!i', '<a href="\1">\1</a>', $str);
zacharyliu
  • 25,578
  • 4
  • 21
  • 15
2

First of all, you need to escape—or even better, replace—the delimeters as explained in the other answers.

preg_replace('~((www|http://)[^ ]+)~', '<a href="\1">\1</a>', $str);

Secondly, to further improve the regex, the $n replacement reference syntax is preferred over \\n, as stated in the manual.

preg_replace('~((www|http://)[^ ]+)~', '<a href="$1">$1</a>', $str);

Thirdly, you are needlessly using capturing parentheses, which only slows things down. Get rid of them. Don't forget to update $1 to $0. In case you are wondering, these are non-capturing parentheses: (?: ).

preg_replace('~(?:www|http://)[^ ]+~', '<a href="$0">$0</a>', $str);

Finally, I would replace [^ ]+ with the shorter and more accurate \S, which is the opposite of \s. Note that [^ ]+ does not allow spaces, but accepts newlines and tabs! \S does not.

preg_replace('~(?:www|http://)\S+~', '<a href="$0">$0</a>', $str);
Geert
  • 1,804
  • 15
  • 15
1
preg_replace('!((?:www|http://)[^ ]+)!', '<a href="\1">\1</a>', $str);

When you use / as your pattern delimiter, having / inside your pattern will not work out well. I solved this by using ! as the pattern delimiter, but you could escape your slashes with backslashes instead.

I also didn't see any reason why you were doing two paren captures, so I removed one of them.

Part of the trouble in your situation is that you're running with warnings suppressed; if you had error_reporting(E_ALL) on, you'd have seen the messages PHP is trying to generate about your delimiter problem in your regex.

chaos
  • 122,029
  • 33
  • 303
  • 309
1

Your main problem seems to be that you are putting everything in parentheses, so it doesn't know what "\1" is. Also, you need to escape the "/". So try this:

preg_replace('/(www|http:\/\/[^ ]+)/', '<a href="\1">\1</a>', $str);

Edit: It actually seems the parentheses were not an issue, I misread it. The escaping was still an issue as others also pointed out. Either solution should work.

Sasha
  • 1,190
  • 7
  • 10
  • I'd just like to add that back references are numbered by the opening parenthesis. For example, in the regexp "T(e(st))", \1 contains "est", and \2 contains "st". – Bravery Onions Jul 04 '09 at 21:53
1

If there are multiple url contained in a string a separated by a line break instead of a space, you have to use the \S

preg_replace('/((www|http:\/\/)\S+)/', '<a href="$1">$1</a>', $val);
Thanh Trung
  • 3,566
  • 3
  • 31
  • 42