Попытка удалить шестнадцатеричные коды из результатов регулярного выражения

Мой первый вопрос здесь в так!
К точке;

Я - симпатичный newbish когда дело доходит до регулярных выражений.
Чтобы изучить это немного лучше и создать что-то, что я могу на самом деле использовать, я пытаюсь создать regexp, который найдет все теги CSS в файле CSS.

До сих пор я использую:

[#.]([a-zA-Z0-9_\-])*

Который работает довольно прекрасный и находит #TB_window а также #TB_window img#TB_Image и .TB_Image#TB_window.

Проблема - это, также находит шестнадцатеричные теги кода в файле CSS. т.е. #FFF или #eaeaea.
.png или .jpg или и 0.75 найдены также..

На самом деле довольно логично, что они найдены, но не являются там умными обходными решениями для этого?
Как исключение чего-либо между скобками {..}?
(Я вполне уверен, это возможно, но мой опыт regexp очень еще не).

Заранее спасибо!

Удачи!
Mike

5
задан Eggie 3 February 2010 в 23:48
поделиться

4 ответа

CSS - это очень простой, обычный язык, что означает, что его можно полностью разобрать с помощью Regex. В нем есть только группы селекторов, за каждой из которых следует группа опций, разделенных двоеточиями.

Обратите внимание, что все регексы в этом посте должны иметь флаги verbose и dotall (/s и /x на некоторых языках, re.DOTALL и re.VERBOSE на Python).

Получить пары (селекторы, правила):

\s*        # Match any initial space
([^{}]+?)  # Ungreedily match a string of characters that are not curly braces.
\s*        # Arbitrary spacing again.
\{         # Opening brace.
  \s*      # Arbitrary spacing again.
  (.*?)    # Ungreedily match anything any number of times.
  \s*      # Arbitrary spacing again.
\}         # Closing brace.

Это не сработает в редких случаях, когда в селекторе атрибутов имеется цитируемая фигурная скобка (например, img[src~='{abc}']) или в правиле (например, background: url('images/ab{c}.jpg')). Это можно исправить, усложнив регекс еще немного:

\s*        # Match any initial space
((?:       # Start the selectors capture group.
  [^{}\"\']           # Any character other than braces or quotes.
  |                   # OR
  \"                  # An opening double quote.
    (?:[^\"\\]|\\.)*  # Either a neither-quote-not-backslash, or an escaped character.
  \"                  # And a closing double quote.
  |                   # OR
  \'(?:[^\']|\\.)*\'  # Same as above, but for single quotes.
)+?)       # Ungreedily match all that once or more.
\s*        # Arbitrary spacing again.
\{         # Opening brace.
  \s*      # Arbitrary spacing again.
  ((?:[^{}\"\']|\"(?:[^\"\\]|\\.)*\"|\'(?:[^\'\\]|\\.)*\')*?)
           # The above line is the same as the one in the selector capture group.
  \s*      # Arbitrary spacing again.
\}         # Closing brace.
# This will even correctly identify escaped quotes.

Вау, это горстка. Но если вы подойдёте к нему по модульному принципу, то заметите, что он не так сложен, как кажется на первый взгляд.

Теперь, чтобы разделить селекторы и правила, нам нужно сопоставить строки символов, которые либо не являются разделителями (где разделитель - это запятая для селекторов и точка с запятой для правил), либо цитируемые строки с чем-нибудь внутри. Мы будем использовать тот же шаблон, который мы использовали выше.

Для селекторов:

\s*        # Match any initial space
((?:       # Start the selectors capture group.
  [^,\"\']             # Any character other than commas or quotes.
  |                    # OR
  \"                   # An opening double quote.
    (?:[^\"\\]|\\.)*   # Either a neither-quote-not-backslash, or an escaped character.
  \"                   # And a closing double quote.
  |                    # OR
  \'(?:[^\'\\]|\\.)*\' # Same as above, but for single quotes.
)+?)       # Ungreedily match all that.
\s*        # Arbitrary spacing.
(?:,|$)      # Followed by a comma or the end of a string.

Для правил:

\s*        # Match any initial space
((?:       # Start the selectors capture group.
  [^,\"\']             # Any character other than commas or quotes.
  |                    # OR
  \"                   # An opening double quote.
    (?:[^\"\\]|\\.)*   # Either a neither-quote-not-backslash, or an escaped character.
  \"                   # And a closing double quote.
  |                    # OR
  \'(?:[^\'\\]|\\.)*\' # Same as above, but for single quotes.
)+?)       # Ungreedily match all that.
\s*        # Arbitrary spacing.
(?:;|$)      # Followed by a semicolon or the end of a string.

Наконец, для каждого правила мы можем разделить (один раз!) двоеточие, чтобы получить пару свойство-значение.

Поместив все это вместе в программу на Python (регексы те же, что и выше, но без обратной связи, чтобы сэкономить место):

import re

CSS_FILENAME = 'C:/Users/Max/frame.css'

RE_BLOCK = re.compile(r'\s*((?:[^{}"\'\\]|\"(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\')+?)\s*\{\s*((?:[^{}"\'\\]|"(?:[^"\\]|\\.)*"|\'(?:[^\'\\]|\\.)*\')*?)\s*\}', re.DOTALL)
RE_SELECTOR = re.compile(r'\s*((?:[^,"\'\\]|\"(?:[^"\\]|\\.)*\"|\'(?:[^\'\\]|\\.)*\')+?)\s*(?:,|$)', re.DOTALL)
RE_RULE = re.compile(r'\s*((?:[^;"\'\\]|\"(?:[^"\\]|\\.)*\"|\'(?:[^\'\\]|\\.)*\')+?)\s*(?:;|$)', re.DOTALL)

css = open(CSS_FILENAME).read()

print [(RE_SELECTOR.findall(i),
        [re.split('\s*:\s*', k, 1)
         for k in RE_RULE.findall(j)])
       for i, j in RE_BLOCK.findall(css)]

Для этого образца CSS:

body, p#abc, #cde, a img .fgh, * {
  font-size: normal; background-color: white !important;

  -webkit-box-shadow: none
}

#test[src~='{a\'bc}'], .tester {
  -webkit-transition: opacity 0.35s linear;
  background: white !important url("abc\"cd'{e}.jpg");
  border-radius: 20px;
  opacity: 0;
  -webkit-box-shadow: rgba(0, 0, 0, 0.6) 0px 0px 18px;
}

span {display: block;} .nothing{}

... мы получаем (для ясности):

[(['body',
   'p#abc',
   '#cde',
   'a img .fgh',
   '*'],
  [['font-size', 'normal'],
   ['background-color', 'white !important'],
   ['-webkit-box-shadow', 'none']]),
 (["#test[src~='{a\\'bc}']",
   '.tester'],
  [['-webkit-transition', 'opacity 0.35s linear'],
   ['background', 'white !important url("abc\\"cd\'{e}.jpg")'],
   ['border-radius', '20px'],
   ['opacity', '0'],
   ['-webkit-box-shadow', 'rgba(0, 0, 0, 0.6) 0px 0px 18px']]),
 (['span'],
  [['display', 'block']]),
 (['.nothing'],
  [])]

Простое упражнение для читателя: напишите регекс для удаления CSS-комментариев (/* ... */).

2
ответ дан 15 December 2019 в 06:26
поделиться

А как насчет этого:

([#.]\S+\s*,?)+(?=\{)
1
ответ дан 15 December 2019 в 06:26
поделиться

Возможно, файл cms_sample_data содержит ошибку. можно использовать следующую команду: manage.py loaddata cms_sample_data

to проверьте файл.

-121--4518446-

Не основывайте обнаружение на пользовательском агенте. Есть много других браузеров, которые используют трезубец 4 (тот, который IE6 использовать), которые не IE6.

Ответ прост: не обнаруживают браузер , обнаруживают механизм . Для этого необходимо использовать обнаружение на основе функции .


Использование обнаружения на основе функций имеет следующие преимущества:

  • Обнаруживает все браузеры, использующие механизм визуализации, аналогичный целевому.
  • Упрощение ветвления кода для решения проблем механизма визуализации.
  • Меньше ложных срабатываний (UA могут быть изменены для передачи в качестве другого браузера, функции не могут).

Следующий сценарий использует функции браузера для обнаружения ядра. Кредит производственной группе MooTools ( http://mootools.net/developers/ ).

Примечание. Приведенный ниже фрагмент изменен для работы без рамки MooTools javascript. Если вы хотите работать с MooTools , вам больше не нужен этот код, он является частью дистрибутива.

function $tryCatch(){
    for (var i = 0, l = arguments.length; i < l; i++){
        try {
            return arguments[i]();
        } catch(e){}
    }
    return null;
};

var Browser = {

    Engine: {name: 'unknown', version: 0},

    Platform: {name: (window.orientation != undefined) ? 'ipod' : (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()},

    Features: {xpath: !!(document.evaluate), air: !!(window.runtime), query: !!(document.querySelector)},

    Plugins: {},

    Engines: {

        presto: function(){
            return (!window.opera) ? false : ((arguments.callee.caller) ? 960 : ((document.getElementsByClassName) ? 950 : 925));
        },

        trident: function(){
            return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ? ((document.querySelectorAll) ? 6 : 5) : 4);
        },

        webkit: function(){
            return (navigator.taintEnabled) ? false : ((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) : 419);
        },

        gecko: function(){
            return (!document.getBoxObjectFor && window.mozInnerScreenX == null) ? false : ((document.getElementsByClassName) ? 19 : 18);
        }

    }

};

Browser.Platform[Browser.Platform.name] = true;

Browser.detect = function(){

    for (var engine in this.Engines){
        var version = this.Engines[engine]();
        if (version){
            this.Engine = {name: engine, version: version};
            this.Engine[engine] = this.Engine[engine + version] = true;
            break;
        }
    }

    return {name: engine, version: version};

};

Browser.detect();

Browser.Request = function(){
    return $tryCatch(function(){
        return new XMLHttpRequest();
    }, function(){
        return new ActiveXObject('MSXML2.XMLHTTP');
    }, function(){
        return new ActiveXObject('Microsoft.XMLHTTP');
    });
};

Browser.Features.xhr = !!(Browser.Request());

Browser.Plugins.Flash = (function(){
    var version = ($tryCatch(function(){
        return navigator.plugins['Shockwave Flash'].description;
    }, function(){
        return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version');
    }) || '0 r0').match(/\d+/g);
    return {version: parseInt(version[0] || 0 + '.' + version[1], 10) || 0, build: parseInt(version[2], 10) || 0};
})();

function $exec(text){
    if (!text) return text;
    if (window.execScript){
        window.execScript(text);
    } else {
        var script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');
        script[(Browser.Engine.webkit && Browser.Engine.version < 420) ? 'innerText' : 'text'] = text;
        document.head.appendChild(script);
        document.head.removeChild(script);
    }
    return text;
};

Просто включите этот класс JavaScript, и вы можете обнаружить IE6 и любой другой браузер с помощью механизма Trident4, выполнив следующие действия:

if(Browser.Engine.trident4) {
   alert('IE6 or similar...');
} elseif(Browser.Engine.name == "trident") {
   alert('Internet Explorer Trident Rendering Engine Version ' + Browser.Engine.version);
}
-121--2290287-

Это на самом деле непростая задача для решения с помощью регулярных выражений, поскольку существует много возможностей, рассмотрим:

  • Селекторы потомков, такие как # someid ul img - все они являются допустимыми тэгами и разделены пробелами
  • тэгами, которые не начинаются с . или # (т.е. имена HTML тэга) - вы должны предоставить список таких имен, чтобы соответствовать им, поскольку они не имеют другого отличия от атрибутов
  • комментирует
  • больше, что я не могу думать сейчас

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

0
ответ дан 15 December 2019 в 06:26
поделиться
ints.Aggregate("", ( str, n ) => str +","+ n ).Substring(1);

Я также думал, что есть более простой способ. Не знаете о производительности, у кого-нибудь есть какая-то (теоретическая) идея?

-121--752905-

Убедитесь, что компилятор лицензий (lc.exe) может найти расположение сборок Infragistics. Кроме того, если компоненты были обновлены в последнее время, убедитесь в отсутствии нескольких копий с разными номерами версий. Наконец, убедитесь, что в файле licenses.licx используется одна и та же версия.

Простой способ обновления лицензии.licx - открыть конструктор форм, добавить компонент Infragistics и удалить его.

Если по какой-либо причине файл licenses.licx не обновляется, можно сначала попытаться удалить ошибочные записи, а затем обновить их.

-121--1646523-

Во-первых, я не вижу, как проведенный вами RE найдет окно .TB _ Image # TB _ . Можно выполнить следующее действие:

/^[#\.]([a-zA-Z0-9_\-]*)\s*{?\s*$/

При этом будут обнаружены любые вхождения # или . в начале строки, за ним следует тег, дополнительно - {, а затем - новая строка.

Обратите внимание, что это НЕ будет работать для строк, таких как .TB _ Image {something: 0;} (все в одной строке) или div.mydivclass , начиная с . не находится в начале строки.

Edit : Я не думаю, что вложенные фигурные скобки разрешены в CSS, поэтому, если вы прочитаете все данные и избавитесь от новых строк, вы можете сделать что-то вроде:

/([a-zA-Z0-9_\-]*([#\.][a-zA-Z0-9_\-]+)+\s*,?\s*)+{.*}/

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

0
ответ дан 15 December 2019 в 06:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: