By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
448,703 Members | 1,165 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 448,703 IT Pros & Developers. It's quick & easy.

Why this RegExp doesn't work

P: n/a
Hi

I am wondering why I couldn't get what I want in the following 3 cases
of re:

(A)

var p=/([a-zA-Z]+-?[a-zA-Z]+):([a-zA-Z0-9]+)/g
p.exec("style='font-size:12'")
--[font-size:12,font-size,12] // expected

(B)

p.exec("style='font-size:12;border-color:red'")
--[border-color:red,border-color,red]
// expected: [font-size:12,font-size,12,
border-color:red,border-color,red]

(C) Note the pattern below is the same as that above:

/([a-zA-Z]+-?[a-zA-Z]+):([a-zA-Z0-9]+)/g.exec("style='font-size:12;border-color:red'")
--[font-size:12,font-size,12]

I expected to get both font-size and border-color reported. However, in
case (B) only border-color is reported, and in case (C) only font-size
reported. The weirdest thing is that (B) and (C) are only different in
how it is used -- in (B) the pattern is assigned to a variable before
use, in (C) the pattern is used directly.

Nov 3 '06 #1
Share this Question
Share on Google+
6 Replies


P: n/a
runsun pan wrote on 03 nov 2006 in comp.lang.javascript:
var p=/([a-zA-Z]+-?[a-zA-Z]+):([a-zA-Z0-9]+)/g

p.exec("style='font-size:12;border-color:red'")
--[border-color:red,border-color,red]
// expected: [font-size:12,font-size,12,
border-color:red,border-color,red]
try this:

<script type='text/javascript'>

var p=/[a-z]+-[a-z]+:[a-z0-9]+/gi
alert( p.exec("style='font-size:12; border-color:red'") )
alert( p.exec("style='font-size:12; border-color:red'") )

</script>

--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
Nov 3 '06 #2

P: n/a

Evertjan. wrote:
try this:

<script type='text/javascript'>

var p=/[a-z]+-[a-z]+:[a-z0-9]+/gi
alert( p.exec("style='font-size:12; border-color:red'") )
alert( p.exec("style='font-size:12; border-color:red'") )

</script>
They give:
--[font-size:12] // first alert
--[border-color:red] // 2nd alert

This doesn't solve my questions. What I want is to solve it in one try.
I thought that's what the /g is for. If you have to run once more for
each match inside of the string, then, doesn't that mean that the /g
(global flag) is useless here ?

Nov 3 '06 #3

P: n/a

runsun pan написав:
This doesn't solve my questions. What I want is to solve it in one try.
I thought that's what the /g is for. If you have to run once more for
each match inside of the string, then, doesn't that mean that the /g
(global flag) is useless here ?
One more version:

var p=/[a-zA-Z]+-?[a-zA-Z]+:[a-zA-Z0-9]+/g
var res = "style='font-size:12;border-color:red'".match(p);
for(var i=0; i<res.length; i++)
{
alert(res[i]+","+res[i].split(":"));
}

Nov 3 '06 #4

P: n/a
This doesn't solve my questions. What I want is to solve it in one try.
I thought that's what the /g is for. If you have to run once more for
each match inside of the string, then, doesn't that mean that the /g
(global flag) is useless here ?
It seems you might need to read up on perl regex.

Basically the /g means that it works on the whole string. So for
example if you were looking for this
/hello/g
and you have the string:
hello there this is a hello statement

then the /g would match both the first and second hellos. Normally the
regex will stop after it matches the condition.

Likewise to get the value in the array you want add () arround the
sections that you wish to seperate out.

For example you have:

font-size: 12px;
/([a-z]*?-[a-z]*?):.([0-9]*)px/
That will return on blah.match(regex).toSource();
[font-size: 12px, font-size, 12]

Or there abouts, havent tested it. The () adds that section of the
regex element in the string to matches[1 .. N]

Make sense?

Nov 3 '06 #5

P: n/a

runsun pan wrote:
Evertjan. wrote:
try this:

<script type='text/javascript'>

var p=/[a-z]+-[a-z]+:[a-z0-9]+/gi
alert( p.exec("style='font-size:12; border-color:red'") )
alert( p.exec("style='font-size:12; border-color:red'") )

</script>

They give:
--[font-size:12] // first alert
--[border-color:red] // 2nd alert

This doesn't solve my questions. What I want is to solve it in one try.
I thought that's what the /g is for. If you have to run once more for
each match inside of the string, then, doesn't that mean that the /g
(global flag) is useless here ?
Wanna do everything with one command and without cycles? ;)

var found=[]
"style='font-size:12;border-color:red'".replace(/([a-z]+-?[a-z]+):([a-z0-9]+)/gi,function(s){found.push(s.split(":"))})
alert(found)

The problem in exec method, not in regexp.
Note: I use .replace() method but there is no replacement in code
above, only matching

Nov 3 '06 #6

P: n/a
runsun pan wrote:
I am wondering why I couldn't get what I want in the following 3
cases of re:
You're expecting things to work in ways that shouldn't happen.
var p=/([a-zA-Z]+-?[a-zA-Z]+):([a-zA-Z0-9]+)/g
p.exec("style='font-size:12'")
--[font-size:12,font-size,12] // expected
The RegExp.prototype.exec method attempts to find the first pattern
match in its argument. Here, it discovers "font-size:12", so the method
stops and returns an array containing details of the match. As the
global flag is set for the regular expression object, the lastIndex
property of the regular expression is modified to point just beyond the
end of the match: to the last apostrophe, in this case.
(B)

p.exec("style='font-size:12;border-color:red'")
--[border-color:red,border-color,red]
That isn't actually what you receive. You've executed this straight
after the previous test, therefore the change in the lastIndex property
described above is significant. If this call was made separately, the
same result as above would be returned. That is, information about the
font-size declaration.
// expected: [font-size:12,font-size,12,
border-color:red,border-color,red]
That will never happen. The exec method only cares about the first (or
more generally, the next) match. Once it finds it (or the string has
been exhaustively searched with no match) the method will return.

As in a recent thread, "regexp test function behavior"[1], you too have
misunderstood how both the global flag and the exec method works. The
point of the former is, as I wrote in that thread, to allow repeated
processing by tracking where the last match ended. A follow-up call can
then resume from that point.

Some regular expression-related methods, most notably the
String.prototype.match and replace methods use the global flag to infer
that this repetitive process should be performed by the method itself,
using the behaviour of the RegExp.prototype.exec method to accomplish
that goal. If you want that same behaviour, you have to implement it
yourself:

String.prototype.detailedMatch = function(regExp) {
var lastMatch = regExp.lastIndex = 0,
result = [],
match;

while ((match = regExp.exec(this))) {
result[result.length] = match;
if (regExp.lastIndex == lastMatch) ++regExp.lastIndex;
lastMatch = regExp.lastIndex;
}
return result;
};

Calling that:

'style="font-size:12;border-color:red"'.detailedMatch(
/([a-zA-Z]+-?[a-zA-Z]+):([a-zA-Z0-9]+)/g);

would result in:

[[font-size:12,font-size,12],
[border-color:red,border-color,red]]

which is easy to observe with:

Array.prototype.toString = function() {
return '[' + this.join() + ']';
};

Compare that result with just the String.prototype.match method:

[font-size:12,border-color:red]

Mike
[1] regexp test function behavior
"HopfZ" <ho******@gmail.com>
Sun, 29 Oct 2006 12:02:42 (UTC)
<11**********************@h48g2000cwc.googlegroups .com>

<http://groups.google.co.uk/group/comp.lang.javascript/msg/87d9d504bf05393d>
Nov 3 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.