Regex для соответствия цветам CSS

Я пытаюсь написать регулярное выражение, которое извлекает все шестнадцатеричные цвета из кода 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 ) ) 

Я не знаю, как указать, что будут совпадать только те цвета, которые заканчиваются пунктуацией, пробелом или новой строкой.

Поскольку шестнадцатеричный цветовой код может также состоять из 3 символов, вы можете определить обязательную группу и необязательную группу букв и цифр, поэтому длинная и продуманная нотация будет выглядеть так:

 /#([af]|[AF]|[0-9]){3}(([af]|[AF]|[0-9]){3})?\b/ 

Или, если вам нужна хорошая и короткая версия, вы можете сказать, что хотите либо 1 или 2 группы из 3 буквенно-цифровых символов, и что они должны быть сопоставлены с регистром ( /i ).

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

Более короткая версия ответа GolezTrol, позволяющая дважды записывать набор символов:

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

В принятом ответе показано, как это сделать с регулярным выражением, потому что это был ваш вопрос. Но вам действительно не нужно использовать regex для этого. Обычно я так делаю:

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

для 100 000 итераций:

Regex solution *: 0.0802619457245 секунд

Xdigit with strlen: 0.0277080535889 секунд

*: hex: ([a-fA-F0-9]{6})

Я не совсем уверен, правильно ли я прав, но если вы хотите согласовать шестнадцатеричные цвета в конце строки 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;')) 

Несмотря на возраст этого вопроса, я хотел бы изменить следующее:

^#([[:xdigit:]]{3}){1,2}$ , где [[:xdigit:]] является сокращением для [a-fA-F0-9] .

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