views:

409

answers:

3

This regular expression fails in Firefox but works in IE.

function validate(x) {
   return /.(jpeg|jpg)$/ig.test(x);
}

Can anybody explain why?

+3  A: 

In regex expressions, "." by itself means "any character". Did you mean "\." to mean "period"?

James Bailey
+2  A: 

The function is using a regular expression pattern .(jpeg|jpg)$ to test strings. It looks like the intent is to validate filenames to make sure they have an extension of either jpg or jpeg.

As James Bailey pointed out, there is an error in that the period should be escaped with a backslash. A period in a regular expression will match any character. So, as shown, the pattern would match both imagexjpg and image.jpg.

Michael Petito
+2  A: 

If you are testing with just the filename, then setting the 'g' flag for greedy doesn't make much sense since you are matching at the end of the string anyway - i ran the following:

function validate(x) {
  return /\.(jpeg|jpg)$/i.test(x);
}

var imagename = 'blah.jpg';
alert (validate(imagename));    // should be true
imagename = 'blah.jpeg';
alert (validate(imagename));    // should be true
imagename = 'blah.png';
alert (validate(imagename));    // should be false

all three tests came out as expected in FF.

As for 'how it works' - regular expressions can get quite tricky - but I will explain the details of the above pattern:

  • the slash / is used to delimit the pattern
  • the dot . has a special meaning of 'any non-whitespace character' - writing it as \. forces the patten to only match a fullstop
  • the () mean a collection (it gets more complicated, but that covers this usage)
  • the | means 'or'
  • $ means the end of the string (or the end of a line in a multi-line text)
  • the i after the second slash means 'case insensitive'
  • the g means 'greedy' - which doesn't make much sense, so I removed it.

so..

/\.(jpeg|jpg)$/i

means "a string ending in either .jpeg or .jpg - ignoring case"

so... .JPEG, .jpg, .JpeG, etc... will all pass now...

HorusKol
Or, reading straight from the RE, it matches a string "with a dot followed by either 'jpeg' or 'jpg', all at the end and ignoring case"
outis
thanks a lot man I just removed the g and add the forward slash infront of "."..it works great man cool
jamal
The `g` means "global", not "greedy" according to the ECMAScript Language Specification section 15.10.4.1. However, it *is* probably not needed here, so removing it would be a good plan.
Tim
I think they mean the same thing though, don't they? I came into RegEx from PHP and Perl, so I tend to default to their terms...
HorusKol
ack - morning coffee has kicked in and I realised I was thinking fuzzily... global and greedy are not the same thing at all... - global = all matches in a string - greedy = match as much as possible in a single pattern
HorusKol