Regex in python to get javadoc-style comments in CSS
I'm writing a python script to loop开发者_StackOverflow through a directory of CSS files and save the contents of any which contain a specifically-formatted javadoc style comment.
The comment/CSS looks like this:
/**thirdpartycss
* @description Used for fixing stuff
*/
.class_one {
margin: 10px;
}
#id_two {
padding: 2px;
}
The regex to fetch the entire contents of the file looks like this:
pattern = "/\*\*thirdpartycss(.*?)}$"
matches = re.findall(pattern, css, flags=re.MULTILINE | re.DOTALL)
This gives me the file contents. What I want to do now is write a regex to grab each CSS definition within the class. This is what I tried:
rule_pattern = "(.*){(.*)}?"
rules = re.findall(rule_pattern, matches[0], flags=re.MULTILINE | re.DOTALL)
I'm basically trying to find any text, then an opening {, any text, then a closing } - I want a list of all of the CSS classes, essentially, but this just returns the entire string in one chunk.
Can anybody point me in the right direction?
Thanks. Matt
{(.*)}
is a greedy match -- it will match from the first {
to the last }
, thus gobble up any {
/}
pairs that might be inside those. You want non-greedy matching, that is
{(.*?)}
the difference is the question mark after the asterisk, making it non-greedy.
This still won't work if you need to properly match "nested" braces -- but then, nothing in the RE world will: among regular languages many well-known limitations (regular languages are those that regular expressions can match) is that "properly nesting" any kind of open/closed parentheses is impossible (some incredibly-extended so-called-RE manage to, but not Python's, and anybody with CS background will find calling those expression "regular" offensive anyway;-). If you need more general parsing than REs can afford, pyparsing or other full-fledged Python parsers are the right way to go.
@Alex is right (is he ever not? but I digress). You are better off using a custom parser if you need more specific parsing than what regular expressions can offer. Luckily you don't have to reinvent the (CSS parsing) wheel. There is an already existing solution for this.
I faced a similar requirement some time back. The cssutils module came in handy at the time. I just refreshed my cssutils fu to cook up this code snippet for you:
In [16]: import cssutils
In [17]: s = """/**thirdpartycss
* @description Used for fixing stuff
*/
.class_one {
margin: 10px;
}
#id_two {
padding: 2px;
}"""
In [26]: sheet = cssutils.parseString(s)
In [27]: sheet.cssRules
Out[27]:
[cssutils.css.CSSComment(cssText=u'/**thirdpartycss\n* @description Used for fixing stuff\n*/'),
cssutils.css.CSSStyleRule(selectorText=u'.class_one', style=u'margin: 10px'),
cssutils.css.CSSStyleRule(selectorText=u'#id_two', style=u'padding: 2px')]
In [28]: sheet.cssRules[0].cssText
Out[28]: u'/**thirdpartycss\n* @description Used for fixing stuff\n*/'
In [29]: print sheet.cssRules[0].cssText
-------> print(sheet.cssRules[0].cssText)
/**thirdpartycss
* @description Used for fixing stuff
*/
You can parse the CSS and then loop through the sheet
object's cssRules
to find all CSSComment
instances.
精彩评论