Alternative to RegExp negative lookbehind assertion for IE

Viewed 1111

There are a lot of questions about lookbehind, But I couldn't find my answer.

My RegExp with negative lookbehind is working fine in chrome but not in IE.

I need a regular expression that match any word after a period(.) but there should not be a (Mr) before the period. for example in

'I met Mr. Jack this evening. He is a good man'

I want to get He, but not Jack (since it is followed by Mr.)

so far I have comeup with the following regExp which works fine on chrome, But it doesn't on IE. and It is to be run on IE.

/(?<!Mr)\. *\b\w+\b/gi

Now I need an alternative to this regex which works on IE. I will also need to exempt (Miss. Mrs. Dr.) after this.

4 Answers

One workaround to achieve this would be by reversing the string, then using negative look-aheads (which are supported by all browsers) - see: https://stackoverflow.com/a/11347100/1954610

Alternatively, you can use negative lookaheads on the existing string too - but it's a bit awkward. Here's a solution for only excluding Mr:

/((?!Mr).{2}|^.?)\. *\b\w+\b/gi

In particular, note the edge cases I had to cover here: The match can happen after 0-1 characters, or after 2 characters that were not "Mr".

Extending this to include Dr is quite easy:

/((?![MD]r).{2}|^.?)\. *\b\w+\b/gi

However, extending this to include Mrs and Miss is much harder - since you now need to account for different length look-aheads. Such regex would end up very confusing. Here's my best attempt, but I'm not entirely convinced it covers all edge cases. (Maybe if someone can cross check it??...)

/(^.?|(?!Miss)(^|.)(?!Mrs)(^|.)(?![MD]r).{2})\. *\b\w+\b/

Demo

...Or alternatively, admittedly as a very ugly workaround, here's a regex to test the string backwards:

\b\w+\b *\.(?!(rM|rD|srM|ssiM))

Demo

You could make use of the ability to use capturing groups with this pattern:

bad_sequence|(good_sequence)

We do actually match the bad stuff, but we only "remember" the valid results by virtue of the capturing parentheses around the second part of the alternation.

so it becomes simply this (note how we use 'grouping only' parens in the first part):

(?:Mr|Mrs|Miss|Dr)\.\s*|\.\s*(\w+)

your "valid words coming after a period", are now in Group 1.

DEMO

(?!(?:Miss|Mr|Dr)\.)(?:\b\w+\b)(\. *\b\w+\b)

Input:

I met Mr. Jack this evening. He is a good man. And Miss. Jack is a good woman. Dr. Jack, how ever is not that great

Output:

. He
. And
. Dr

Fortunately, IE does support negative look ahead. Expanding your pattern \. *\b\w+\b to match both the word before and after the . allows you to negate the match with the look ahead, and capture the second part.

I would do this in two steps. Step 1, match the unwanted Words, then replace them with an empty string, then the string is ready to be parsed for dots. Here's the first regex:

/(?:Mr|Mrs|Miss|Dr)\./gi

Now replace those matches with an empty string.

Now match the fixed string with this regex:

/\s*\b\w+\b/gi

That will give the result you want.

Related