ObiHill
ObiHill

Reputation: 11886

Regex for checking presence and absence of keywords in User Agent String

I'm using a Regex in Javascript to sniff the User Agent string. Here is some pseudo code below:

is_not_tablet_bool = /android.+mobile/i.test(navigator.userAgent.toLowerCase());
switch(true)
{
     case (is_not_tablet_bool):
         return true;
     break;
}

I'm trying to craft a regex that will do something close to the opposite of the above i.e.

  1. ensure that 'android' keyword is present in string, and at the same time
  2. ensure that 'mobile' keyword is absent from string

Thanks for the anticipated assistance.

Upvotes: 3

Views: 2143

Answers (2)

Robert Koritnik
Robert Koritnik

Reputation: 105039

Negative lookahead

Regular expressions have a construct called negative lookahead which matches a string in the regular expression without capturing the lookahead part:

Your regular expression should be written this way:

/android(?!.*mobile)/i

This will match any string that contains word android that is not followed by word mobile with ignored case. This also means that you can remove the toLowerCase call.

Addition: Negative lookbehind

In case you need only match those strings that have word android in them but lack mobile (either before or after) then a combination of negative lookaheads and lookbehinds will do.

/(?<!mobile.*)android(?!.*mobile)/i

But the problem is that Javascript doesn't support negative lookbehinds. So you have to employ a different trick that will help you determining that situation.

There are several possibilities of which following seem to be most interesting (and last one useful):

  1. Replace a matching negative string that will fail afterwards:

    var nav = navigator.userAgent.replace(/mobile.*android/, "fail" );
    return /android(?!.*mobile)/i.test(nav);
    
  2. Use two lookaheads. One on normal string and the other on reversed one while also having a reversed regular expression:

    var nav = navigator.userAgent;
    var after = /android(?!.*mobile)/i.test(nav);
    var before = /diordna(?!.*elibom)/i.test(nav.split("").reverse().join(""));
    return before && after;
    
  3. Simplicity is key. Two simple regular expressions would do the trick just fine as well:

    var nav = navigator.userAgent;
    return /android/i.test(nav) && !/mobile/i.test(nav);
    

Note: I'm not sure whether your code is actual code, because if it is I would strongly recommend you reconsider the use of switch(true) statement and simply replace it by
return is_not_tablet_bool;.

Upvotes: 6

maerics
maerics

Reputation: 156464

I don't think using regular expressions makes this task any easier. I would simply check for the inclusion and exclusion of those strings using the String.indexOf(...) method:

function isNotAndroidMobile(userAgentString) {
  var ua = userAgentString.toLowerCase();
  return (ua.indexOf('android')>=0) && (ua.indexOf('mobile')===-1);
}

Upvotes: 0

Related Questions