Regex for matching CSS hex colors

后端 未结 5 1076
傲寒
傲寒 2021-02-02 07:33

I\'m trying to write regex that extracts all hex colors from CSS code.

This is what I have now:

Code:

$css = <<

        
相关标签:
5条回答
  • 2021-02-02 08:09

    Despite this question's age I'd like to ammend the following:

    ^#([[:xdigit:]]{3}){1,2}$, where [[:xdigit:]] is a shorthand for [a-fA-F0-9].

    So:
    <?php preg_match_all("/^#(?>[[:xdigit:]]{3}){1,2}$/", $css, $matches) ?>

    Also noteworthy here is the usage of a non-capturing group (?>...), to ensure we don't store data in memory we never wanted to store in the first place.

    Try it online

    0 讨论(0)
  • 2021-02-02 08:15

    Since a hex color code may also consist of 3 characters, you can define a mandatory group and an optional group of letters and digits, so the long and elaborate notation would be:

    /#([a-f]|[A-F]|[0-9]){3}(([a-f]|[A-F]|[0-9]){3})?\b/
    

    Or if you want a nice and short version, you can say that you want either 1 or 2 groups of 3 alphanumeric characters, and that they should be matched case insensitively (/i).

    /#([a-f0-9]{3}){1,2}\b/i
    

    Instead of [a-f0-9] you can also write [[:xdigit:]], if the regex engine supports this posix character class. In this case you can skip the /i at the end, and the whole formula is only two characters more, but arguably more descriptive.

    /#([[:xdigit:]]{3}){1,2}\b
    
    0 讨论(0)
  • 2021-02-02 08:18

    The accepted answer shows you how to do it with regex, because that was your question. But you really don't need to use regex for this. Normally this is how I would do it:

    if(ctype_xdigit($color) && strlen($color)==6){
        // yay, it's a hex color!
    }
    

    for 100.000 iterations:

    Regex solution *: 0.0802619457245 seconds

    Xdigit with strlen: 0.0277080535889 seconds

    *: hex: ([a-fA-F0-9]{6})

    0 讨论(0)
  • 2021-02-02 08:25

    I'm not entirely sure if I got this right, but if you only want to match hex colors at the end of a CSS line:

    preg_match_all('/#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})[\s;]*\n/',$css,$matches);
    

    should work, all I did was add the optional \s; char group (optional semi-colon and spaces) and a line-break character (not optional) and it seemed to work.
    And as @GolezTrol pointed out #FFF; is valid, too.

    When tested on this:

    $css = '/* Do not match me: #abcdefgh; I am longer than needed. */
    .foo
    {
        color: #CAB;
        background-color:#ababab;
    }';
    preg_match_all('/#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})[\s;]*\n/',$css,$matches);
    var_dump($matches);
    

    The output was:

    array (array('#CAB;','#ababab;'))
    
    0 讨论(0)
  • 2021-02-02 08:28

    Shorter version of GolezTrol's answer that avoids writing the character set twice:

    /#([a-fA-F0-9]{3}){1,2}\b/
    
    0 讨论(0)
提交回复
热议问题