Regex not matching against ampersand

Viewed 109

I'm trying to match the following regex:

\b(?:mr|mrs|ms|miss|messrs|mmes|dr|prof|rev|sr|jr|&|and)\.?\b

In other words, a word boundary followed by any of the strings above (optionally followed by a period character) followed by a word boundary.

I'm trying to match this in Java, but the ampersand will not match. For example:

Pattern p = Pattern.compile(
        "\\b(?:mr|mrs|ms|miss|messrs|mmes|dr|prof|rev|sr|jr|&|and)\\.?\\b", 
        Pattern.CASE_INSENSITIVE);
    
String result = p.matcher("mr one and mrs.two and three & four").replaceAll(" ");
    
System.out.println("["+result+"]");

The output of this is: [ one two three & four]

I've also tried this at regex101, and again the ampersand does not match: https://regex101.com/r/klkmwl/1

Escaping the ampersand does not make a difference, and I've tried using the hex escape sequence \x26 instead of ampersand (as suggested in this question). Why is this not matching?

2 Answers

Your regex will match an ampersand if it is located in between word chars, e.g. three&four, see this regex demo. This happens because \b before a non-word char requires a word char to appear immediately before it. Also, as there is a \b after an optional dot, both the dot and ampersand will only match if there is a word char immediately on the left.

You need to re-write the pattern so that the word boundaries are applied to the words rather than symbols:

Pattern p = Pattern.compile(
        "(?:\\b(?:mr|mrs|ms|miss|messrs|mmes|dr|prof|rev|sr|jr|and)\\b|&)\\.?", 
        Pattern.CASE_INSENSITIVE);

See the regex demo online.

Problem is due to use of word boundaries. There are no word boundaries before or after a non-word character like &.

In place of word boundary you can use lookarounds:

(?<!\w)(?:[jsdm]r|mr?s|miss|messrs|mmes|prof|re|&|and)\.?(?!\w)

Updated RegEx Demo

  • (?<!\w): Make sure that previous character is not a word character
  • (?!\w): Make sure that next character is not a word character

Note some tweaks in your regex to make it shorter.

Related