Как я могу правильно проанализировать шестнадцатеричный цветовой код в Python, используя Regex? - PullRequest
2 голосов
/ 20 октября 2019

Я новичок в Regex, поэтому я продолжаю практиковать, выполняя все упражнения, которые могу найти. В одном из них мне нужно извлечь все шестнадцатеричные коды из исходного кода HTML, используя Regex и Python. Согласно упражнению, правила определения шестнадцатеричного кода:

  1. Он начинается с #
  2. Он состоит из 3 или 6 цифр
  3. Каждая цифра вдиапазон 0-F (строка не чувствительна к регистру)

Пример ввода такой:

#BED
{
    color: #FfFdF8; background-color:#aef;
    font-size: 123px;
    background: -webkit-linear-gradient(top, #f9f9f9, #fff);
}
#Cab
{
    background-color: #ABC;
    border: 2px dashed #fff;
}

Желаемый результат:

#FfFdF8
#aef
#f9f9f9
#fff
#ABC
#fff

#BED и #Cab должны быть опущены, поскольку они не являются шестнадцатеричными цветами.

Я попытался использовать этот код для решения проблемы:

import re

text = """
#BED
{
    color: #FfFdF8; background-color:#aef;
    font-size: 123px;
    background: -webkit-linear-gradient(top, #f9f9f9, #fff);
}
#Cab
{
    background-color: #ABC;
    border: 2px dashed #fff;
} """

r = re.compile(r'#[0-9A-Fa-f]{3}|[0-9A-Fa-f]{6}')
a = r.findall(text)
print(a)

Полученный вывод:

['#BED', '#FfF', '#aef', '#f9f', '#fff', '#Cab', '#ABC', '#fff']

Работает нормально, за исключением того, что не перехватывает 6-значные коды и не устраняет два тега, которыена самом деле это не шестнадцатеричные цветовые коды.

Что я ошибаюсь? Я посмотрел на другие попытки, но они не дали правильный ответ. Я использую Python 3.7.4 и последнюю версию PyCharm.

Ответы [ 3 ]

4 голосов
/ 20 октября 2019

С одной стороны, вы можете сопоставить 6-значные коды сначала , в противном случае совпадение с 3-значными кодами сначала будет соответствовать половине из них (и, таким образом, не совпадать с полными 6-значными кодами). Но так как вы также хотите сопоставлять только правила свойств CSS, а не селекторы, обратите внимание на ;, , или ):

(?i)#(?:[0-9a-f]{6}|[0-9a-f]{3})(?=[;,)])

https://regex101.com/r/BtZaoV/2

Есливам также нужно иметь возможность исключить комбинированные селекторы, например, #BED, foo {, вы можете посмотреть не { s, а затем }:

(?i)#(?:[0-9a-f]{6}|[0-9a-f]{3})(?=[^{]*})

https://regex101.com/r/BtZaoV/3

Используйте флаг без учета регистра, чтобы все было сухо. (вы также можете использовать {3}){1,2}, чтобы не повторять набор символов, но это усложнит чтение шаблона IMO)

1 голос
/ 20 октября 2019

Вы можете попробовать

#(?:[0-9A-Fa-f]{6}|[0-9A-Fa-f]{3})(?=;|[^(]*\))

Таким образом, здесь идея соответствует 6 длина символа с более высоким приоритетом, если не найдено совпадение 3 совпадение символов, чтобы убедиться, что оно не соответствует #BED или что-то ещенам нужно сопоставить завершение шестнадцатеричного цветового кода, поэтому мы используем прогноз с чередованием

enter image description here

Regex Demo

0 голосов
/ 20 октября 2019

Вы можете использовать

r = re.compile(r'#[0-9A-Fa-f]{3}(?:[0-9A-Fa-f]{3})?(?!$)', re.M)

См. пруф

Пример кода Python:

import re
regex = r"#[0-9A-Fa-f]{3}(?:[0-9A-Fa-f]{3})?(?!$)"
test_str = ("#BED\n"
    "{\n"
    "    color: #FfFdF8; background-color:#aef;\n"
    "    font-size: 123px;\n"
    "    background: -webkit-linear-gradient(top, #f9f9f9, #fff);\n"
    "}\n"
    "#Cab\n"
    "{\n"
    "    background-color: #ABC;\n"
    "    border: 2px dashed #fff;\n"
    "}")
matches = re.findall(regex, test_str, re.MULTILINE)
print(matches)
...