#python #css #regex #string #hex
Вопрос:
Я пытаюсь извлечь все допустимые шестнадцатеричные значения, которые представляют цвет в CSS
коде.
Технические характеристики шестнадцатеричного цветового кода
- Оно должно начинаться с символа»#».
- Он может содержать 3 или 6 цифр.
- Каждая цифра находится в диапазоне 0-F или 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
Объяснение
#КРОВАТЬ и #Кабина удовлетворяют критериям шестнадцатеричного цветового кода, но они используются в качестве селекторов, а не в качестве цветовых кодов в данном CSS. Таким образом, фактические цветовые коды являются
#FfFdF8
#aef
#f9f9f9
#fff
#ABC
#fff
Что я пробовал в python
import re
pattern = r'^#([A-Fa-f0-9]{3}){1,2}
Когда я запускаю приведенный выше код на примере ввода, он ничего не печатает.
Так что же плохого я здесь делаю? Это совпадающий шаблон? Или это та логика, которую я применяю?
Пожалуйста, кто-нибудь, объясните мне!
Комментарии:
1. Ваш шаблон закреплен с
^
помощью и$
. Таким образом, он будет совпадать только в том случае, если вся строка представляет собой одно шестнадцатеричное число, оно не будет совпадать в середине строки.2. Спасибо @Barmar, я изменил шаблон на
r'(#([A-Fa-f0-9]{3}){1,2})'
, теперь он соответствует#FfFdF8
, но такжеdF8
. Теперь, что я должен сделать, чтобы он соответствовал только#FfFdF8
?3. Я не понимаю, как это может совпадать
df8
, когда это не начинается с#
самого начала .4. Избавьтесь от групп захвата, вам это не нужно
findall()
. Это возвращает группы вместо всего матча.5. Итак, что я должен использовать вместо
findall()
этого, чтобы получить желаемый результат?
Ответ №1:
Избавьтесь от якорей ^
и $
, поскольку они делают его соответствующим только всей входной строке.
Избавьтесь от групп захвата, чтобы re.findall()
возвращались только целые совпадения, а не групповые совпадения. Используйте (?:...)
для создания группы без захвата, чтобы вы могли использовать {1,2}
квантификатор.
pattern = r'#(?:[A-Fa-f0-9]{3}){1,2}'
Ответ №2:
У вас проблема из двух или трех частей:
- Удалите комментарии CSS, которые часто содержат материалы, похожие на код (необязательно, но рекомендуется).
- Комментарии, соответствующие регулярному выражению, являются
/*.*?*/
- Комментарии, соответствующие регулярному выражению, являются
- Смотрите только внутрь фигурных скобок (например, не на селекторы).
- Регулярное выражение, соответствующее фигурным скобкам, является
{.*?}
- Регулярное выражение, соответствующее фигурным скобкам, является
- найдите цветовые коды
- Регулярное выражение для цветовых кодов является
#(?:[A-Fa-f0-9]{3}){1,2}
- Регулярное выражение для цветовых кодов является
Сводя все это воедино:
import re
def color_codes(css_text):
codes = []
# remove comments
css_text = re.sub(r'/*.*?*/', '', css_text, re.S)
# consider only {} blocks
for block in re.finditer(r'{.*?}', css_text, re.S):
# find color codes
codes.extend(re.findall(r'#(?:[A-Fa-f0-9]{3}){1,2}', block.group(0)))
return codes
Примечание: Это, вероятно,не надежное решение. Для этого вам нужно переключиться с простого регулярного выражения на полный синтаксический анализатор. Но это достаточно близко, если вам просто нужно что-то быстрое и вы не возражаете против некоторых крайних случаев.
n = int(input())
hexNum = []
for _ in range(n):
s = input()
if ':' in s and '#' in s:
result = re.findall(pattern,s)
if result:
hexNum.extend(result)
for num in hexNum:
print(num)
Когда я запускаю приведенный выше код на примере ввода, он ничего не печатает.
Так что же плохого я здесь делаю? Это совпадающий шаблон? Или это та логика, которую я применяю?
Пожалуйста, кто-нибудь, объясните мне!
Комментарии:
1. Ваш шаблон закреплен с
^
помощью и$
. Таким образом, он будет совпадать только в том случае, если вся строка представляет собой одно шестнадцатеричное число, оно не будет совпадать в середине строки.2. Спасибо @Barmar, я изменил шаблон на
r'(#([A-Fa-f0-9]{3}){1,2})'
, теперь он соответствует#FfFdF8
, но такжеdF8
. Теперь, что я должен сделать, чтобы он соответствовал только#FfFdF8
?3. Я не понимаю, как это может совпадать
df8
, когда это не начинается с#
самого начала .4. Избавьтесь от групп захвата, вам это не нужно
findall()
. Это возвращает группы вместо всего матча.5. Итак, что я должен использовать вместо
findall()
этого, чтобы получить желаемый результат?
Ответ №1:
Избавьтесь от якорей ^
и $
, поскольку они делают его соответствующим только всей входной строке.
Избавьтесь от групп захвата, чтобы re.findall()
возвращались только целые совпадения, а не групповые совпадения. Используйте (?:...)
для создания группы без захвата, чтобы вы могли использовать {1,2}
квантификатор.
Ответ №2:
У вас проблема из двух или трех частей:
- Удалите комментарии CSS, которые часто содержат материалы, похожие на код (необязательно, но рекомендуется).
- Комментарии, соответствующие регулярному выражению, являются
/*.*?*/
- Комментарии, соответствующие регулярному выражению, являются
- Смотрите только внутрь фигурных скобок (например, не на селекторы).
- Регулярное выражение, соответствующее фигурным скобкам, является
{.*?}
- Регулярное выражение, соответствующее фигурным скобкам, является
- найдите цветовые коды
- Регулярное выражение для цветовых кодов является
#(?:[A-Fa-f0-9]{3}){1,2}
- Регулярное выражение для цветовых кодов является
Сводя все это воедино:
Примечание: Это, вероятно,не надежное решение. Для этого вам нужно переключиться с простого регулярного выражения на полный синтаксический анализатор. Но это достаточно близко, если вам просто нужно что-то быстрое и вы не возражаете против некоторых крайних случаев.