Подтвердить что ты не робот

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
        )

)

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

4b9b3361

Ответ 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;'))