I have rebuild all but one line, the one with only the url.
<?php
$input = "[url=http://stackoverflow.com]stackoverflow[/url]
[url=http://stackoverflow.com]http://stackoverflow.com/damn[/url]
http://stackoverflow.com/ok
[url=http://stackoverflow.com][img]url_to_img[/img][/url]
[url=http://stackoverflow.com][b]stackoverflow[/b][/url]
[url=http://stackoverflow.com][b][u][i]stackoverflow[/i][/u][/b][/url]
[url=http://stackoverflow.com][color=red]stackoverflow[/color][/url]
[url=http://stackoverflow.com][h1][color=red]stackoverflow[/color][/h1][/url]";
$match = [
'/\[url=([^\]]+)\](.*)\[\/url\]/im',
'/\[img\](.*)\[\/img\]/im',
'/\[b\](.*)\[\/b\]/im',
'/\[u\](.*)\[\/u\]/im',
'/\[i\](.*)\[\/i\]/im',
'/\[color=([^\]]+)\](.*)\[\/color\]/im',
'/\[h([1-6])\](.*)\[\/h(?:[1-6])\]/im',
];
$replace = [
'<a href="$1">$2</a>',
'<img src="$1">',
'<strong>$1</strong>',
'<u>$1</u>',
'<em>$1</em>',
'<span style="color:$1;">$2</span>',
'<h$1>$2</h$1>',
];
echo preg_replace($match, $replace, $input);
This is giving the following output:
<a href="http://stackoverflow.com">stackoverflow</a>
<a href="http://stackoverflow.com">http://stackoverflow.com/damn</a>
http://stackoverflow.com/ok
<a href="http://stackoverflow.com"><img src="url_to_img"></a>
<a href="http://stackoverflow.com"><strong>stackoverflow</strong></a>
<a href="http://stackoverflow.com"><strong><u><em>stackoverflow</em></u></strong></a>
<a href="http://stackoverflow.com"><span style="color:red;">stackoverflow</span></a>
<a href="http://stackoverflow.com"><h1><span style="color:red;">stackoverflow</span></h1></a>
The one matching only the url is a bit trickier. It depends on how advanced you want it to be. It may detect simple stuff like example.com or more advanced stuff like ☃.net (which results in http://xn--n3h.net/)
Some explanation
First rule we are trying to match and replace is a url code. We simple start of by searching for appearance of [url=, simple and hardcoded. What we are looking for next might be a lot of things, but one thing we know for sure is that we have to end with a ]. We can then use a regular expression which says: match all but ] ([^\]]+) Note that I escaped the ] character, else the match will fail.
Next i again search for everything ((.*)) until we reach a hardcoded expected value, [/url].
This is pretty much the whole match rule for every type of bbcode you wanted.
As for the replace part you include what they should be replaced with, simple. To add the values matched in the regex, use $1, $2, ..., $n. A match is defined by my parentheses.
For an example: '/[url=([^]]+)](.*)[/url]/im'
The two parentheses segments in bold is the segments which contains the values we will be getting from $1and $2
I tried my best to explain how this worked. If something is still unclear, point it out, and I will try my best to explain further