6

I'm looking for some regex for this kind of strings

rgb(r,g,b)
rgba(r,g,b,a)
hsl(h,s%,l%)
hsla(h,s%,l%,a)

with:

r,g,b integer included between 0 and 255, 
a float between 0 and 1 (truncated to first digit after the point)
h integer included between 0 and 359
s,l integer included between 0 and 100

For rgb, I wrote those regex:

rgb\(\s*((?:[0-2]?[0-9])?[0-9])\s*,\s*((?:[0-2]?[0-9])?[0-9])\s*,\s*((?:[0-2]?[0-9])?[0-9])\s*\)$

It works, but it also allows strings like rgb(299,299,299). How can I make it more effective? What about rgba,hsl and hsla? Thanks

kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 2
    http://stackoverflow.com/questions/6560030/what-regex-can-i-use-to-validate-a-number-between-0-and-255 => don't use a regex to validate that a number falls within a range... – assylias Sep 12 '12 at 09:57
  • 1
    And this: http://stackoverflow.com/questions/10682737/regex-statement-for-only-numbers-between-0-and-255-in-c-sharp – assylias Sep 12 '12 at 10:00
  • @AntonioGiovanniSchiavone More for readability and maintenance reason. Which do you prefer: `^(0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])$` or `if number >= 0 && number <= 255 {...}`? – assylias Sep 12 '12 at 10:33
  • For integer between 0 and 255 seems to work: ^(0|[1-9]\d?|1\d\d?|2[0-4]\d|25[0-5])$ for float between 0 and 1: ^((0.[1-9])|[01])$ – Antonio Giovanni Schiavone Sep 12 '12 at 10:34
  • @assylias Sorry, I accidentally deleted the previuos messagge, I rewrote it. Yes, it's less clear, ma probably more quick. This code is just for personal use. – Antonio Giovanni Schiavone Sep 12 '12 at 10:43
  • 1
    @AntonioGiovanniSchiavone the important word in *"probably more quick"* is probably. 1. I don't think regex will be quicker 2. if it is, the difference will be a matter of milliseconds (if not less), so hardly noticeable, even if you run that code millions of times... – assylias Sep 12 '12 at 10:48

3 Answers3

8

Finally I wrote these regex:

    String keywords_color_regex = "^[a-z]*$";
    String hex_color_regex = "^#[0-9a-f]{3}([0-9a-f]{3})?$";
    String rgb_color_regex = "^rgb\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%?\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%?\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%?\\s*\\)$";
    String rgba_color_regex = "^rgba\\(\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%?\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%?\\s*,\\s*(0|[1-9]\\d?|1\\d\\d?|2[0-4]\\d|25[0-5])%?\\s*,\\s*((0.[1-9])|[01])\\s*\\)$";
    String hsl_color_regex = "^hsl\\(\\s*(0|[1-9]\\d?|[12]\\d\\d|3[0-5]\\d)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*,\\s*((0|[1-9]\\d?|100)%)\\s*\\)$";

I'm developing a library for my personal use, so I prefer to use regex. I fully commented the code. Thanks for the tips!

JeanValjean
  • 17,172
  • 23
  • 113
  • 157
  • 1
    check this out if you need it in javascript https://gist.github.com/Safareli/10603775 – Safareli Apr 13 '14 at 21:48
  • 2
    Your rgba_color_regex matches `(0.[1-9])|[01])` at the end, which should be `(0.[0-9]*)|[01])` to allow alpha values such as 0.05 or 0.74 for example. Otherwise great, thanks! You could also copy the `,\\s*((0.[1-9])|[01])\\s*\\ ` part at the end of the "rgba" regex and append to the end of "hsl" to make a new "hsla" line. – Kristian Sandström Oct 23 '14 at 08:42
  • 1
    @Safareli you're missing the fact that in JS (due to CSS), RGB value can be defined in `%` like `rgb(100%, 50%, 90%)` – Roko C. Buljan Jul 11 '15 at 16:07
  • Just note that we may have a negative number in RGB and RGBA. This will be clipped to 0 by the browser, but it still does not pass the regex. Anyway, this kind of bestiality should not appear in the code :) – JeanValjean Aug 25 '17 at 08:22
6

I can see two solutions for you. Either :

1. Extract the numbers from the inputs and then check them with if conditions

a) Regex

rgb\(\s*(?:(\d{1,3})\s*,?){3}\)

b) Visual description

Simple regular expression for parsing a RGB value

2. Build a (rather complex) regex to check the inputs directly

a) Regex

rgb\(\s*(?:(?:\d{1,2}|1\d\d|2(?:[0-4]\d|5[0-5]))\s*,?){3}\)$

rdb(0,0,255) => OK
rdb(104,10,299) => KO
rdb(299,5,299) => KO

b) Visual description

A more robust regular expression for parsing a RGB value


Tips :

  • Regex allowing integer included between 0 and 359

    \d{1,2}|[1-2]\d{2}|3[0-5]\d

  • Regex allowing integer included between 0 and 100

    \d{1,2}|100

Conclusion

As a general rule of thumb, for the maintainability of the code prefer the solution #1. A developer not involved in regular expression would understand quite quickly what's going on. Don't forget to fully comment the code.

If you prefer solution #2 then be prepared to have developers with a good background in regular expression as the regular expression is complex.

Stephan
  • 41,764
  • 65
  • 238
  • 329
  • 2
    I know this is an old post, but I was about to mark a question as duplicate until I saw you made the comma optional in your regex, allowing to match `rgb(112233)` [DEMO](https://regex101.com/r/dM2cL5/1) – Mariano Sep 20 '15 at 04:08
3

Hex

/[\#]([a-fA-F\d]{6}|[a-fA-F\d]{3})/gm

RGB

/[Rr][Gg][Bb][\(](((([\d]{1,3})[\,]{0,1})[\s]*){3})[\)]/gm

RGBA

/[Rr][Gg][Bb][Aa][\(](((([\d]{1,3}|[\d\.]{1,3})[\,]{0,1})[\s]*){4})[\)]/gm

HSL

/[Hh][Ss][Ll][\(](((([\d]{1,3}|[\d\%]{2,4})[\,]{0,1})[\s]*){3})[\)]/gm

HSLA

/[Hh][Ss][Ll][Aa][\(](((([\d]{1,3}|[\d\%]{2,4}|[\d\.]{1,3})[\,]{0,1})[\s]*){4})[\)]/gm
HovyTech
  • 299
  • 5
  • 19