This caught me at first – but upon closer inspection it makes sense – I was writing something that was looking at the User Agent of a device to see if it was Android using the “test” regex method and got the opposite result from what I was expecting. I expected that the “test” regex on the UA for the word “Android” would return true but instead I always got false. Here’s an example:

...
var isAnd = /Android/gi;
console.log(isAnd.test(navigator.userAgent));
...

On the surface this should be true, yet it returns false in the console. See this next example:

...
var isAnd = /Android/gi;
console.log(isAnd.test('android'));
...

Now the above returns true – something in the UA string is breaking the test. Here are the UA’s that I’ve tried with the above:

  • Galaxy Tab 2: Mozilla/5.0 (Linux; U; Android 4.1.1;en-us; GT-P5113 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Safari/534.30
  • Nexus 7: Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19

On a whim I remove the forward slashes and perform the following test:

...
var isAnd = /Android/gi;
console.log(isAnd.test('Mozilla5.0 (Linux; Android 4.1.1; Nexus 7 BuildJRO03D) AppleWebKit535.19 (KHTML, like Gecko) Chrome18.0.1025.166  Safari535.19'));
...

Ah, this is what we’re looking for, that test works. So in order to do a successful pattern match using the “test” regular expression method on the User Agent string you would have to first remove all instances of “/” or escape them with a backslash (\/).

In Regular Expressions certain characters have a special meaning – I would think that a string that the regex is being run on would be immune but that’s apparently not the case. Forward slashes are used to create regular expression literals and if present within the string, well…. who knows what happens, presumeably its interpreted as another regular expression – and then things just won’t work. For that reason forward slashes need to be escaped with another character that has a special meaning in regular expressions – the backslash. So, this “\/” actually represents a single literal forward slash.

Yeah, this gets a little messy, you could do one of two things. You could clean the UA string first by using something like this (which, btw, is a little aggressive but is a good example of what you can do):

...
var str = 'some big string that needs to be "cleaned"';
str.replace(/([\[\]\*\^\&\$\.\(\)\?\/\\\+\{\}\|])/g, "\\$1");
...

Or, and I like this approach a lot for this particular application, you could just use a different method entirely, such as the “search” regex method, which is impervious to this situation:

...
var ua = navigator.userAgent.toLowerCase();
console.log(ua.search('android') != -1)
...

And this gives us the predictable “true” as a result.