0

Regular expressions often eludes me. I am struggling to understand an unexpected result with grouping, and would like someone to tell me:

  • Why it is not working as intended
  • How I could achieve the expected result

Context:

I'm working with strings containing hex color codes. I use replace() on that string to "feed" the matched color codes to a function returning HTML - kind of a parameterized string. One of the parameters is ok, but the other matches the whole string?

Some code:

Here is a JSFiddle with a simple example (beware: does not take letters as far as hex codes go).

The fiddle's code:

HTML:

<p>Please enter two hex color codes (digits only)</p>
<input id="colorsInput" type="text"></input>
<button id="booyah">Roll</button>
<p>Teh colorz</p>
<div id="colors"></div>
<p>Teh source</p>
<div id="html"></div>

JS:

$(document).ready(function() {

  function parameterizedHtml(p1, p2) {
    return '<div style="background-color:#' + p1 + '; width:50px; height:50px;">&nbsp;</div><div style="background-color:#' + p2 + '; width:50px; height:50px;">&nbsp;</div>'; 
  }    

  $('#booyah').click(function() {
    var colorsString = $('#colorsInput').val();
    var html = colorsString.replace(/(\d{6}).*(\d{6})/, parameterizedHtml);
    $('#html').text(html);
    $('#colors').html(html);
  });

});

Output:

<div style="background-color:#548423 564212; width:50px; height:50px;">&nbsp;</div><div style="background-color:#548423; width:50px; height:50px;">&nbsp;</div>

Notice the first background-color attribute.

Silver Quettier
  • 2,045
  • 2
  • 26
  • 53
  • 1
    You use [callback](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Specifying_a_function_as_a_parameter) for `replace` improperly. It expect 1st parameter to be the whole match, not the 1st submatch which corresponds to 2nd parameter. – hindmost Aug 04 '14 at 08:46

2 Answers2

1

The first argument replace gives to the callback function is the overall match. That's then followed by additional arguments for any capture groups. So if you change your function signature to:

function parameterizedHtml(match, p1, p2)

...it will start working as expected.

Here's an updated fiddle with the change. I've also changed the regex to /([a-f0-9]{6}).*([a-f0-9]{6})/i so it accepts hex, but note that numeric color values are not required to be six digits long. They can also be three digits long. #abc is the same as #aabbcc. If you want to accept both, then: /([a-f0-9]{3}|[a-f0-9]{6}).*([a-f0-9]{3}|[a-f0-9]{6})/i.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Excellent! I should have read the manual better, I can't believe I missed that one. - Thank you for the updated RegEx, I already had the `[a-f]` part in mind, but did not think about 3-character color codes, this will come in handy. Bonus question: would you say matching `[a-fA-F0-9]` or casting to lowercase and matching `[a-f0-9]` is better? – Silver Quettier Aug 04 '14 at 09:09
  • 1
    @SilverQuettier: In the above, I used the `i` flag on the regex, which is for a case-insensitive match. So no need to do anything to make the string lowercase. I don't think it much matters whether you use the `i` flag or use `[a-fA-F0-9]`. :-) – T.J. Crowder Aug 04 '14 at 09:48
0

So your regex is looking for digits, not hex. Assuming you are looking for two color codes in one input, I would go with

^([0-9a-fA-F]{6})[^0-9a-fA-F]*([0-9a-fA-F]{6})

With this, you start with 6 hex chars, then any amount of non hex chars (including none), then another 6 hex chars. This also accounts for upper and lower case hex alphas. And then the parenthesis will capture the first color and second color separately.

XlogicX
  • 642
  • 6
  • 10
  • 1
    Thank you for your input. However as I stated in the question, this was merely a simple example to showcase the "unexpected matching", and I did not bother with proper hex matching, which was not the root of my mistake. (See T.J.'s answer above.) – Silver Quettier Aug 04 '14 at 09:08
  • fair enough :). You had me at regex and I missed the rest :( – XlogicX Aug 04 '14 at 09:46