Match if the line has two or more of the same capitalized word

Viewed 42

Basically I want to match this:

So this. So that. [this should match]

Yes this. No that. [this shouldn't match]

I thought this would work:

(\b(\w+)\1\b.*){2,}

But right now, it's matching the second line too: https://regexr.com/5jhag

Why is this and how to fix it?

2 Answers

Match if the line has two or more of the same capitalized word

As you want to match capitalized words only a \w is not right because it matches [a-zA-Z0-9_] characters. Also using \1 just after the capture group means consecutive repeats only. Finally \b is also required around matches.

You may use this regex:

\b([A-Z]\w*)\b.*\b\1\b

RegEx Demo

RegEx Details:

  • \b: Word boundary
  • ([A-Z]\w*): Match a capitalize word that start with uppercase letter followed by 0 or more of any word characters
  • \b: Word boundary
  • .*: Match 0 or more of any characters
  • \b\1\b: Match same word as what we captured in group #1 surrounded with word boundaries

(\b(\w+)\1\b.*){2,} is a repeated capturing group. \1 is a backreference that references the value of the group it is defined in and it is always assigned an empty string, at each iteration. Note: if you were to test with PCRE engine, there would be no match, see proof, because \1 is not empty, it is null and there is no match.

Your regex matches Yes this. No that. because the current expression is equal to (\b(\w+)\b.*){2,} and matches any word, then any text, two times or more.

Use

.*\b([A-Z][a-zA-Z]+)\b.*\b\1\b.*

See proof.

Unicode version:

.*\b(\p{Lu}\p{L}+)\b.*\b\1\b.*

See another proof.

Explanation

--------------------------------------------------------------------------------
  .*                       any character except \n (0 or more times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  (                        group and capture to \1:
--------------------------------------------------------------------------------
    [A-Z]                    any character of: 'A' to 'Z'
--------------------------------------------------------------------------------
    [a-zA-Z]+                any character of: 'a' to 'z', 'A' to 'Z'
                             (1 or more times (matching the most
                             amount possible))
--------------------------------------------------------------------------------
  )                        end of \1
--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  .*                       any character except \n (0 or more times
                           (matching the most amount possible))
--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  \1                       what was matched by capture \1
--------------------------------------------------------------------------------
  \b                       the boundary between a word char (\w) and
                           something that is not a word char
--------------------------------------------------------------------------------
  .*                       any character except \n (0 or more times
                           (matching the most amount possible))
Related