I ended up going with this. I then passed it do a callback which allows me to do some special code in php for some link checking:
# MATCH '?://www.link.com' and make it a bbcode link
$URLRegex = '/(?:(?<!(\[\/link\]|\[\/link=))(\s|^))'; // No [url]-tag in front and is start of string, or has whitespace in front
$URLRegex.= '('; // Start capturing URL
$URLRegex.= '(https?|ftps?|ircs?|http?|ftp?|irc?):\/\/'; // Protocol
$URLRegex.= '\S+'; // Any non-space character
$URLRegex.= ')'; // Stop capturing URL
$URLRegex.= '(?:(?<![[:punct:]])(\s|\.?$))/i';
$output = preg_replace($URLRegex, "$2[link=$3]$3[/link]$5", $output);
# MATCH 'www.link.com' and make it a bbcode link
$URLRegex2 = '/(?:(?<!(\[\/link\]|\[\/link=))(\s|^))'; // No [url]-tag in front and is start of string, or has whitespace in front
$URLRegex2.= '('; // Start capturing URL
$URLRegex2.= 'www.'; // Protocol
$URLRegex2.= '\S+'; // Any non-space character
$URLRegex2.= ')'; // Stop capturing URL
$URLRegex2.= '(?:(?<![[:punct:]])(\s|\.?$))/i';
$output = preg_replace($URLRegex2, "$2[link=http://$3]$3[/link]$5", $output);
# link up a [link=....]some words[/link]
$output = preg_replace_callback(
"/\[link=(.*?):\/\/(.*?)\](.*?)\[\/link\]/is",
Array($this,'bbcode_format_link1'),
$output);