tags:

views:

188

answers:

2

I'm wanting to scan through a css file and capture both comments and the css. I've came up with a regex that's almost there, however it's not quite perfect as it misses out properties with multiple declarations i.e.

ul.menu li a, # Won't capture this line
ul.nice-menu li a { text-decoration: none; cursor:pointer; }

Here's the regex that I'm working with:

(\/\*[^.]+\*\/\n+)?([\t]*[a-zA-Z0-9\.# -_:@]+[\t\s]*\{[^}]+\})

I've been testing this at rubular.com and here is what it currently matches, and what the array output is like.

Result 1

[0] /* Index */
/*
GENERAL

PAGE REGIONS
- Header bar region
- Navigation bar region
- Footer region           
SECTION SPECIFIC
- Homepage
- News */

[1] html { background: #ddd; }

Result 2

[0]
[1] body { background: #FFF; font-family: "Arial", "Verdana", sans-serif; color: #545454;}

I must point out that I'm still a new when it comes to regular expressions, so if anyone can help and show where I'm going wrong, it'd be much appreciated :)

+3  A: 

CSS cannot be fully parsed with a regex (see CSS Grammar: http://www.w3.org/TR/CSS2/grammar.html). The {...} can be split over lines, for example, and your current version wouldn't handle this. If you need to do this, you should read the CSS spec and use a tool like ANTLR to generate a parser.

Here is an example from the W3C spec (http://www.w3.org/TR/CSS2/syndata.html):

@import "subs.css";
@import "print-main.css" print;
@media print {
  body { font-size: 10pt }
}
h1 {color: blue }

No normal regex is powerful enough to deal with nested {...} etc. let alone the contents of the imported stylesheets.

peter.murray.rust
remove all newlines and he'll be safe!
thephpdeveloper
@Mauris then there will be a single line.
peter.murray.rust
@Mauris he won't. just think of "{" inside comments, strings, ... he should definitely go with a specialized css parser.
ax
+1. Regex is not the way to go when trying to parse css
Yacoby
I'm going for a simple case - no nested curly braces {...}The regex that I'm currently working with matches declarations that span over multiple lines.If someone can manage to tweak the current one to handle with the case outlined above, I'd be very grateful!
Damian
@Damian: yes, it's often possible to choose a specific subset of a language that you can write a parser for, but as soon as you get into the open world you will immediately find examples that break your tools. That's why it's important to adhere to standards and use existing tools rather that writing your own. You'll end up with a lot of work and it will still keep breaking
peter.murray.rust
@Peter In that case can you point me in the right direction to achieve what I'm after?
Damian
@Damian - I would look for CSS parser and PHP. I think there are CSS parsers in many languages
peter.murray.rust
@Damian here is an SO page that gives links to PHP CSS parsers and also discusses your problem
peter.murray.rust
A: 

What language are you using?

You should probably just use a library to parse the CSS. Libraries can save you a lot of grief.

Jørgen Fogh
I'm using PHP, and preg_match_all
Damian
@Damian: there are PHP CSS parsers already.
PhiLho