Regex для соответствия цветам CSS
Я пытаюсь написать regex, который извлекает все шестнадцатеричные цвета из 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
)
)
Я не знаю, как указать, что будут совпадать только те цвета, которые заканчиваются пунктуацией, пробелом или новой линией.
Ответы
Ответ 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
Вместо [a-f0-9]
вы также можете написать [[:xdigit:]]
, если механизм регулярных выражений поддерживает этот класс символов posix. В этом случае вы можете пропустить /i
в конце, и вся формула будет всего на два символа больше, но, возможно, более наглядной.
/#([[:xdigit:]]{3}){1,2}\b
Ответ 2
Более короткая версия ответа GolezTrol, позволяющая дважды записывать набор символов:
/#([a-fA-F0-9]{3}){1,2}\b/
Ответ 3
Принятый ответ показывает, как это сделать с помощью регулярного выражения, потому что это был ваш вопрос. Но вам действительно не нужно использовать regex для этого. Обычно я так делаю:
if(ctype_xdigit($color) && strlen($color)==6){
// yay, it a hex color!
}
для 100 000 итераций:
Regex solution *: 0.0802619457245 секунд
Xdigit с strlen: 0.0277080535889 секунд
*: hex: ([a-fA-F0-9]{6})
Ответ 4
Несмотря на возраст вопроса, я хотел бы изменить следующее:
^#([[:xdigit:]]{3}){1,2}$
, где [[:xdigit:]]
является сокращением для [a-fA-F0-9]
.
Итак:
<?php preg_match_all("/^#(?>[[:xdigit:]]{3}){1,2}$/", $css, $matches) ?>
Также заслуживает внимания использование группы без захвата (?>...)
, чтобы гарантировать, что мы не храним данные в памяти, которую мы никогда не хотели хранить в первую очередь.
Попробуйте онлайн
Ответ 5
Я не совсем уверен, правильно ли я прав, но если вы хотите согласовать шестнадцатеричные цвета в конце строки CSS:
preg_match_all('/#(?:[0-9a-fA-F]{6}|[0-9a-fA-F]{3})[\s;]*\n/',$css,$matches);
должен работать, все, что я сделал, это добавить необязательную группу \s;
char (необязательная полутоплица и пробелы) и символ прерывания строки (не обязательный), и это, казалось, сработало.
И как @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;'))