Мой первый вопрос здесь в так!
К точке;
Я - симпатичный 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
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-комментариев (/* ... */
).
Возможно, файл cms_sample_data содержит ошибку. можно использовать следующую команду: manage.py loaddata cms_sample_data
to проверьте файл.
-121--4518446-Не основывайте обнаружение на пользовательском агенте. Есть много других браузеров, которые используют трезубец 4 (тот, который IE6 использовать), которые не IE6.
Ответ прост: не обнаруживают браузер , обнаруживают механизм . Для этого необходимо использовать обнаружение на основе функции .
Использование обнаружения на основе функций имеет следующие преимущества:
Следующий сценарий использует функции браузера для обнаружения ядра. Кредит производственной группе 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 разбор библиотеки подходит для вашего предпочтительного языка.
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*)+{.*}/
Есть способ сказать регексу игнорировать новые строки, но я никогда не понимаю, что правильно.