35

我正在尝试编写从 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
        )

)

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

4

5 回答 5

58

由于十六进制颜色代码也可能包含 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 字符类,[a-f0-9]你也可以写而不是写。[[:xdigit:]]在这种情况下,您可以跳过/i最后的 ,整个公式仅多出两个字符,但可以说更具描述性。

/#([[:xdigit:]]{3}){1,2}\b/
于 2012-10-11T10:58:21.160 回答
33

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

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})

于 2016-11-10T11:14:19.403 回答
21

GolezTrol 的答案的较短版本,避免了两次编写字符集:

/#([a-fA-F0-9]{3}){1,2}\b/
于 2015-04-07T04:04:20.247 回答
2

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

^#([[:xdigit:]]{3}){1,2}$, 哪里[[:xdigit:]]是 的简写[a-fA-F0-9]

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

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

在线尝试

于 2017-08-03T07:56:13.160 回答
1

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

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

应该工作,我所做的只是添加可选的\s;字符组(可选的分号和空格)和换行符(非可选),它似乎工作。
正如@GolezTrol 指出的那样#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;'))
于 2012-10-11T11:00:07.603 回答