walmartlabs/backbone-historytracker — pull request #7 by catesandrew (2013-10-10 18:07:09+00:00)
Title: User agent matches Non chrome browser

[MOWEB-3420](https://wmobile.atlassian.net/browse/MOWEB-3420 "[Android]
: Empty search results were being displayed after redirecting to
mobile,for the Search URLs")

[Regular Expression to match string not containing
a word](http://stackoverflow.com/questions/406230)

[Pull Request 7](https://github.com/walmartlabs/backbone-historytracker/pull/7)

The fact that regex doesn't support inverse matching is not entirely
true. You can mimic this behavior by using negative look-arounds:

^((?!Chrome).)*$

The regex above will match any string, or line without a line break,
**not** containing the (sub) string 'Chrome'. As mentioned, this is not
something regex is "good" at (or should do), but still, it *is*
possible.

And if you need to match line break chars as well, use the [DOT-ALL
modifier](http://perldoc.perl.org/perlre.html#Modifiers) (the trailing
`s` in the following pattern):

/^((?!Chrome).)*$/s

or use it inline:

/(?s)^((?!Chrome).)*$/

*(where the `/.../` are the regex delimiters, ie, not part of the
pattern)*

If the DOT-ALL modifier is not available, you can mimic the same
behavior with the character class `[\s\S]`:

/^((?!Chrome)[\s\S])*$/

Explanation
-------

A string is just a list of `n` characters. Before, and after each
character, there's an empty string. So a list of `n` characters will
have `n+1` empty strings. Consider the string `"ABhedeCD"`:

+--+---+--+---+--+---+--+---+--+---+--+---+--+---+--+---+--+
S = |e1| A |e2| B |e3| h |e4| e |e5| d |e6| e |e7| C |e8| D |e9|
+--+---+--+---+--+---+--+---+--+---+--+---+--+---+--+---+--+

index 0 1 2 3 4 5 6 7

where the `e`'s are the empty strings. The regex `(?!Chrome).` looks ahead
to see if there's no substring `"Chrome"` to be seen, and if that is the
case (so something else is seen), then the `.` (dot) will match any
character except a line break. Look-arounds are also called
_zero-width-assertions_ because they don't _consume_ any characters.
They only assert/validate something.

So, in my example, every empty string is first validated to see if
there's no `"Chrome"` up ahead, before a character is consumed by the `.`
(dot). The regex `(?!Chrome).` will do that only once, so it is wrapped in
a group, and repeated zero or more times: `((?!Chrome).)*`. Finally, the
start- and end-of-input are anchored to make sure the entire input is
consumed: `^((?!Chrome).)*$`

As you can see, the input `"ABChromeDE"` will fail because on `e3`, the
regex `(?!Chrome)` fails (there _is_ `"Chrome"` up ahead!).