用于匹配 CSS 十六进制颜色的正则表达式

Posted

技术标签:

【中文标题】用于匹配 CSS 十六进制颜色的正则表达式【英文标题】:Regex for matching CSS hex colors 【发布时间】: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). 【参考方案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;'))

【讨论】:

以上是关于用于匹配 CSS 十六进制颜色的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式匹配所有字符直到到达字符,但也包括最后一个匹配

学习python第十六天,正则表达式

python正则表达式匹配十六进制数据

第十六章 Python正则表达式

正则表达式RegExp

js正则表达式