0

UPDATED

I need some help from you to defeat the regexp! I'm getting the external CSS file in a form of AJAX response like this:

$.when($.get("style.css")).done(function(response) {
    var myCSS = response;
    var patt = new RegExp("#mydiv(.*?)}","g");
    var match = myCSS.match(patt);
    alert(match);  
}

What I'm trying to achieve here is I want to get everything from #mydiv to the last closing bracket }, but for some reason alert(match) returns me null.

The most annoying thing is when I change the pattern to:

var patt = new RegExp("#mydiv(.*?){","g"); // <-- Changed } to {

alert(match) returns me what is supposed to be returned --> #mydiv .mylink {

Or when I represent the same CSS in a form of a simple string like this:

$.when($.get("style.css")).done(function(response) {
    var myCSS = "The same style.css but copy-pasted here";
    var patt = new RegExp("#mydiv(.*?)}","g");
    var match = myCSS.match(patt);
    alert(match);  
}

Works with my initial pattern as expected. Any thoughts what am I missing here?

PointedEars
  • 14,752
  • 4
  • 34
  • 33
LoomyBear
  • 449
  • 2
  • 8
  • 19
  • You will get better results and better insight for future viewers if you post a sample on jsfiddle.net –  Feb 04 '13 at 01:01
  • 1
    Your first example correctly gives me `#mydiv .mylink { background: green; }`, i.e. the expected result. You must have an error elsewhere in your code. – Felix Kling Feb 04 '13 at 01:02
  • 3
    Please don't start a question with “I'm so noob”. We're programmers, not 1337 h4x0rs on CSI. – Jezen Thomas Feb 04 '13 at 01:06
  • @FelixKling Just tried my code on jsFiddle ... yes it works on this example, but I can't make it work on my production code which is quite big and won't fit there %( ... arrrggghhh!!! – LoomyBear Feb 04 '13 at 01:19
  • @JezenThomas Never again! – LoomyBear Feb 04 '13 at 01:19
  • Well, then that's your problem. How do you expect us to help you if the code you posted works totally fine? – Felix Kling Feb 04 '13 at 01:32
  • @FelixKling I've updated the question ... please check – LoomyBear Feb 04 '13 at 01:39
  • @LoomyBear you should take a look at http://txt2re.com. It's a very powerful tool to generate regular expressions based on your own input string. It taught me the ins and outs of regular expressions by using it a couple of times. – Robin van Baalen Feb 04 '13 at 01:48
  • @RobinvanBaalen Hey thanks! I've checked this website a while ago and I still can't get it how it works ))) I used this http://gskinner.com/RegExr/ instead! Very powerful tool to check regexps – LoomyBear Feb 04 '13 at 01:51
  • @LoomyBear Considering your edit, I'd say have a look at: http://stackoverflow.com/questions/247483/http-get-request-in-javascript Your `$.get` javascript doesn't seem right, if for no other reason than `style.css` is no `'style.css'`, but how you're chaining it doesn't seem right either. – Jon Feb 04 '13 at 02:32
  • @Jon I'm not sure what do you mean, but anyway my `$.get` works like expected returning me the correct response. The problem is when I try to parse it with regex for some unknown reason my regex pattern doesn't work like it is expected. That's the problem! – LoomyBear Feb 04 '13 at 08:56
  • @LoomyBear then I am confused, as every example I have tried putting it in works in jsfiddle. If the `$.get` works properly, then I don't see where the error can be if assigning it within the JS works properly as well. – Jon Feb 04 '13 at 09:00
  • @Jon I've updated my question. Please check it out. This is exactly my problem. My pattern works with static(?) string and does not work with AJAX response. – LoomyBear Feb 04 '13 at 09:07
  • @LoomyBear what does `alert(response)` give you at the start of `done`? Is it the correct css? – Jon Feb 04 '13 at 09:11
  • @Jon Yes the style.css is valid. When I try to `alert(response)` it gives me the correct css code, when I try to use different regex pattern `"#mydiv(.*?){"` it returns me what is expected `#mydiv .mylink {` but when I use the pattern I need `"#mydiv(.*?)}"` I get `null` – LoomyBear Feb 04 '13 at 09:19
  • @LoomyBear Try the `/m` modifier with the `/g` (so, `gm`) to see if allowing multi-line matches will help. – Jon Feb 04 '13 at 09:24
  • Look into the Chomsky hierarchy. You cannot parse a *context-free* language like CSS with one application of one *regular* expression because a single regular expression either matches too much or too few characters. You need a parser based on a push-down automaton (stack). The question is, however, why do you think parsing is necessary? – PointedEars Feb 04 '13 at 09:40
  • @Jon It still does not work. But I think the problem really is about this multi lines inside the CSS. The thing is I need a single line string as an output so I guess what I need here is to convert incoming multiline CSS into a single line string which is parsed with my initial regex quite well. Do you know any possible way to do this? – LoomyBear Feb 04 '13 at 10:08
  • maybe replace either `\n` or `\r\n` with `''` to start? – Jon Feb 04 '13 at 10:10
  • @PointedEars Thanx! Sounds really fancy )) Do you know any possible way to convert the incoming CSS into a single line string? – LoomyBear Feb 04 '13 at 10:10
  • Yes, but that will not help as *regular* expressions describe *regular* languages only. An indication that CSS is context-free *and* _not_ regular is that there are *pairs* of brackets in it; there is a basic context-free *bracket language* L₍₎ = a^n b^n that CSS can be transformed into. (You learn that in CS classes.) So regular expressions can only solve a part of the problem: finding the tokens that you are interested in, especially `{` and `}`. Then, with a PDA-based parser, it does not matter how many newline tokens are in-between. The question remains: *Why* do you want to parse CSS? – PointedEars Feb 04 '13 at 10:31
  • @PointedEars I need to parse the initial CSS, find all the rules for elements with IDs `#home { color: green; }` and `#home a { color: yellow; }` replace them with new IDs `#home_new { color: green; } #home_new a { color: yellow }` and insert it as an inline CSS to the HTML. The thing is my regex allows me to parse the simple string like `myCSS = "#home { color:green; } #home a { color: yellow; }"` and the output structure works perfectly normal in the final HTML. But I just can't make it correctly parse the response from the AJAX. Can you advise any way to convert response to a simple string? – LoomyBear Feb 04 '13 at 10:40
  • You are still missing the point and you have still not answered my question. Suppose we could remove unnecessary newlines from the source code (which is possible and easy). That would leave us with `"#home { color: green; } @media screen { #home a { color: yellow; } }"`. Applying `/#home a.*\}/` on that will match too many, applying `/#home.*?\}/` will match too few characters. You need to *find* *pairs* of braces instead which cannot be done with one application of one regular expression. Build/use a CSS parser or reconsider your approach. – PointedEars Feb 04 '13 at 10:47
  • @PointedEars Thanx you've got a very strong point here. The thing is my regex pattern (I'm not telling it is good, but it) works just perfect when I just copy the CSS code to JS variable like this `var myCSS = "my awesome css"`. It parses `myCSS` very well with a very good results. I want to try to convert incoming CSS to a single line string, parse it, and use on my production version ... maybe it will work for me – LoomyBear Feb 04 '13 at 11:07
  • Please move extended discussions to [chat], this comment thread is getting rather lengthy. – Tim Post Feb 04 '13 at 11:10
  • @TimPost Would like to, but for some reason the "Invite to chat" button does not appear here. – PointedEars Feb 04 '13 at 11:11
  • @TimPost @PointedEars Yes I would like to chat, but I think I'm too young for this kind of events ... I'm only 14 %)) `This is my stackoverflow rating duh!` – LoomyBear Feb 04 '13 at 11:18

2 Answers2

1

The } is a reserved character on regex, you have to escape it with \. I think regex you're after is "#mydiv(.*)\}" or "#mydiv(.*)\\}" if the \ itself has to be escaped.

gerrytan
  • 40,313
  • 9
  • 84
  • 99
0

Ok I think I've found the solution.

var patt = new RegExp("#" + myID + "(\n|.)*?}","g");

After crazy googling, stackoverflowing and discussing with the community all night long. I've found that the problem is that JS Regex does not recognize the . as a new line so you need to put (\n|.) instead.

I'm not sure that this solution is universal, and will ty to test it on different CSS files. Thank you guys that commented my post! I really appreciate your collaboration!

Source: the very end of http://goo.gl/1W55l

LoomyBear
  • 449
  • 2
  • 8
  • 19