【问题标题】:Regex for matching CSS hex colors用于匹配 CSS 十六进制颜色的正则表达式
【发布时间】:2012-10-02 00:31:52
【问题描述】:

我正在尝试编写从 CSS 代码中提取所有十六进制颜色的正则表达式。

这就是我现在拥有的:

代码:

$css = <<<CSS

/* Do not match me: #abcdefgh; I am longer than needed. */

.foo
{
    color: #cccaaa; background-color:#ababab;
}

#bar
{
    background-color:#123456
}
CSS;

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

输出:

Array
(
    [0] => Array
        (
            [0] => #abcdef
            [1] => #cccaaa
            [2] => #ababab
            [3] => #123456
        )

)

我不知道如何指定只匹配以标点符号、空格或换行符结尾的颜色。

【问题讨论】:

  • 不要使用正则表达式。请参阅@modu 的回答。 if(ctype_xdigit($color) &amp;&amp; strlen($color)==6).

标签: php css regex colors hex


【解决方案1】:

由于十六进制颜色代码也可能包含 3 个字符,因此您可以定义一个强制组和一个可选的字母和数字组,因此长而详细的符号将是:

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

或者,如果您想要一个漂亮而简短的版本,您可以说您想要 1 组或 2 组 3 个字母数字字符,并且它们应该不区分大小写 (/i)。

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

如果正则表达式引擎支持此 posix 字符类,您也可以写 [[:xdigit:]],而不是 [a-f0-9]。在这种情况下,您可以跳过末尾的/i,整个公式仅多了两个字符,但可以说更具描述性。

/#([[:xdigit:]]{3}){1,2}\b/

【讨论】:

  • 谢谢,\b 正是我们所需要的。不知道为什么有“?”尽管。无论如何,这可以根据需要工作:/#(?:[0-9a-fA-F]{6})\b/ 忘了说不需要 3 个字符代码。
  • 问号要求前面出现 0 次或 1 次,因此第二个捕获的组是可选的。
  • 这些变化毫无意义。这是一个更简单的版本:/#([a-fA-F0-9]){3}(([a-fA-F0-9]){3})?\b/
  • @HamZa 谢谢,没问题。实际上我的正则表达式技能并没有提高多少,因为我很少使用它们。原因之一是可读性差。我对我写的那个很满意,因为它可读性很强,即使它有点多余。就像“普通”代码一样,我认为更短不一定更好。不过,如果它是我的答案的补充而不是完全替代的话,我会留下你的版本。
  • @evolross 它匹配字符串中的颜色代码。它将匹配#FFF#FF 中的#FFF,但不是最后一部分。如果要匹配确切的字符串,可以将字符串边界“锚”添加到正则表达式,使其类似于^#([a-f0-9]{3}){1,2}\b$。请参阅https://regex101.com/r/LZJr63/1 了解详情。
【解决方案2】:

接受的答案向您展示了如何使用正则表达式,因为那是您的问题。但是你真的不需要为此使用正则表达式。通常我会这样做:

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

100.000 次迭代:

正则表达式解 *: 0.0802619457245 秒

带 strlen 的 Xdigit:0.0277080535889 秒

*:十六进制:([a-fA-F0-9]{6})

【讨论】:

  • 谁来调用这个函数10万次?
  • 抱歉,这类事情太疯狂了。在任何给定的 PHP 文件中,该函数最多被调用 5 次?所以我们说的是几分之一毫秒?
  • 这个答案值得更多的支持。代码不仅快 3 倍多,而且更短且更易于理解。
  • 但我想检查一下#你能帮帮我吗
  • 当然,这个答案值得更多的支持。函数在未来比正则表达式更容易理解和支持。
【解决方案3】:

GolezTrol's answer 的较短版本避免了两次写入字符集:

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

【讨论】:

  • 您可以使用i 不区分大小写的匹配标志使其更短。 /#([a-f0-9]{3}){1,2}\b/i
【解决方案4】:

尽管这个问题的年龄我想修改以下内容:

^#([[:xdigit:]]{3}){1,2}$,其中[[:xdigit:]][a-fA-F0-9] 的简写。

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

这里还值得注意的是使用非捕获组(?&gt;...),以确保我们不会将数据存储在我们一开始就不想存储的内存中。

Try it online

【讨论】:

    【解决方案5】:

    我不完全确定我是否正确,但如果您只想匹配 CSS 行末尾的十六进制颜色:

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

    应该可以,我所做的只是添加可选的 \s; 字符组(可选的分号和空格)和换行符(不是可选的),它似乎可以工作。
    正如@GolezTrol 指出的那样out #FFF; 也是有效的。

    当对此进行测试时:

    $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);
    

    输出是:

    array (array('#CAB;','#ababab;'))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 2017-02-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-28
      • 2016-12-03
      • 2017-06-17
      相关资源
      最近更新 更多