用于匹配 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) && 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) ?>
这里还值得注意的是使用非捕获组(?>...)
,以确保我们不会将数据存储在我们一开始就不想存储的内存中。
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 十六进制颜色的正则表达式的主要内容,如果未能解决你的问题,请参考以下文章