Reputation: 72739
I would like to replace (all occurences) of the HTML <font>
-tag in a string.
Example string:
Line1<div><font class="blablabla" color="#33FF33">Line2</font></div><div>Line3
or:
Line1<div><font color="#33FF33">Line2</font></div><div><font color="#FF3300">Li</font>ne3
The font (starttag) should be replaced by the color, so that based on the two examples we get:
Line1<div>33FF33Line2</font></div><div>Line3
Line1<div>33FF33Line2</font></div><div>FF3300Li</font>ne3
I've tried the following (among others :P):
preg_replace('/<font.*color="#([0-9a-fA-F]){6}">/', '{1}', $string)
I think I'm in the right direction, however I think it's more like so close yet so far away :)
When I use it on the string with only 1 fonttag in it, it removes the font tag (I must have messed something up with the replacement {1}). When I use it on the string with multiple fonttags in it, it does the same. But not only removing the first fonttag but everything from the first fonttag to the next (or last) fonttag.
Ok.
Let's just forget about the HTML code parsing discussion for a sec.
What if I had the following texts:
This colorcode (#333333) is so cool
This colorcode (orange: #ff3300) is way cooler
And I wanted the texts to become:
This colorcode 333333 is so cool
This colorcode ff3300 is way cooler
Same situation as I see it, or am I being ignorant now?
Upvotes: 1
Views: 2420
Reputation: 75272
preg_replace('~<font[^>]*\scolor="#([0-9a-fA-F]{6})"[^>]*>~', '$1', $string);
*
and other quantifiers are greedy by default, which is why you got the unintended contraction of the string with multiple font tags; it's just matching too much. You can make them non-greedy by adding a question mark (.*?
), but other factors can still cause them to consume more than you want. It's better in this case to use a more specific expression ([^>]*
) that can't match beyond the tag it starts in.
Besides that, in the code you posted you were using {1}
instead of $1
for the backreference, and you had the quantifier ({6}
) outside the parentheses, so you would only ever capture the last digit, not all six as you intended. That code shouldn't have returned the result you posted, to say nothing of the correct result.
As for your updated question:
preg_replace('~\([^)]*#([0-9a-fA-F]{6})[^)]*\)~', '$1', $string);
Upvotes: 3
Reputation: 67355
RegEx is nice and convenient, but I would question whether or not you could catch every case using RegEx. What about tags within strings, etc?
I wrote some spidering code and ended up just parsing the entire document, element by element. That was the only way I found to make it reliable.
See: http://blackbeltcoder.com/Articles/strings/parsing-html-tags-in-c/
Upvotes: 0