0

I just came across the following function below:

function hexToRgb(hex){
  // By Tim Down - http://stackoverflow.com/a/5624139/3493650
  // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
  var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
  hex = hex.replace(shorthandRegex, function(m, r, g, b) {
     return r + r + g + g + b + b;
  });

Now I tried the following regex in my browser console:

s = "#ddd"
s.match(/^#?([a-f\d])([a-f\d])([a-f\d])$/i) // RESULT ["#ddd", "d", "d", "d"]

Now when I change s to the following:

s = "##ddd"
s.match(/^#?([a-f\d])([a-f\d])([a-f\d])$/i) // null

Why is it null? Why no match, when I check the regex in the regex checker here:

It says the following:

#? matches the character # literally Quantifier: ? Between zero and one time, as many times as possible, giving back as needed [greedy]

Now the above statement says as many times as possible , so why does ##fff not match with the regex /^#?([a-f\d])([a-f\d])([a-f\d])$/i ?

timolawl
  • 5,434
  • 13
  • 29
Alexander Solonik
  • 9,838
  • 18
  • 76
  • 174

3 Answers3

3

You needed the +:

^#+?([a-f\d])([a-f\d])([a-f\d])$

The + matches 1 or more of the preceding token.

The ? makes the preceding quantifier lazy, causing it to match as few characters as possible.

Edit:

It can actually be simplified to ^#+([a-f\d])([a-f\d])([a-f\d])$ since as @TimPietzcker mentioned, the following tokens can't match #.

timolawl
  • 5,434
  • 13
  • 29
2

The explanation given by Regex101 can be misunderstood. I would rewrite it as

"Between zero and one time, preferably one, but also allowing zero if necessary (greedy)"

In general, greedy matching means "try to match as many as possible", but in this case the maximum allowed number is 1.

^#?([a-f\d])

means

  1. Start the match at the beginning of the string.
  2. Match one (optional) #.
  3. Then match a hex digit.

This obviously fails with ##1 (and this isn't affected by laziness or greediness in this case).

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
0

You need a '+' after your hash.

With '+' The preceding item will be matched one or more times.

You regex will be ^#+?([a-f\d])([a-f\d])([a-f\d])$

Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400