Regex to test if there's a word appeared exactly 2 times

Viewed 140

Given a string, test if there's a word appeared exactly two times

Input Pass
apple banana pineapple No
apple banana apple pineapple Yes
apple banana banana pineapple Yes
apple banana apple pineapple apple No
apple banana apple banana Yes
apple banana banana apple pineapple apple Yes

I tried something like this but didn't work :(

^.*(\b\w+\b)(?:(?!\b\1\b).)*\b\1\b(?:(?!\b\1\b).)*$

Any suggestions? I'm using pcre.

2 Answers

Get next word. Stop if it contained exactly 2 times. Loop.

^(?*.*?\b(\w+)\b)(?>.*?\b\1\b){2}(?!.*\b\1\b)

Demo

Using PyPi regex module that allows dynamic length lookbehind:

\b(\w+)\b(?<!\b\1\b.*\b\1\b)(?:(?!\b\1\b).)*?\b\1\b(?!.*\b\1\b)

RegEx Demo

Code:

>>> import regex as re
>>> arr = ["apple banana pineapple", "apple banana apple pineapple", "apple banana banana pineapple",
... "apple banana apple pineapple apple", "apple banana apple banana", "apple banana banana apple pineapple apple"]
>>> reg = re.compile(r'\b(\w+)\b(?<!\b\1\b.*\b\1\b)(?:(?!\b\1\b).)*?\b\1\b(?!.*\b\1\b)')
>>> for i in arr: print (i, '=>', reg.findall(i))
...
apple banana pineapple => []
apple banana apple pineapple => ['apple']
apple banana banana pineapple => ['banana']
apple banana apple pineapple apple => []
apple banana apple banana => ['apple']
apple banana banana apple pineapple apple => ['banana']

RegEx Details:

  • \b(\w+)\b: Match a word with word boundaries and capture in group #1
  • (?<!\b\1\b.*\b\1\b): Dynamic length lookbehind to assert that we have don't another instance of same word before this word
  • (?:(?!\b\1\b).)*?\b\1\b: Match another instance of same word while ensuring we don't match same word in between 2 repeats
  • (?!.*\b\1\b): Finally make there is no other instance of this word ahead of us, thus making sure there are only 2 instances

Earlier Answer:

This regex with a negative lookahead may work:

^(?!.*?\b(\w+)\b(?:.*\b\1\b){2}).*?\b(\w+)\b.*\b\2\b

RegEx Demo

RegEx Details:

  • ^: Start
  • (?!: Negative lookbehind start
    • .*?: Match 0 or more of any characters
    • \b(\w+)\b: Match and capture a word - (?:.*\b\1\b){2}: If same word is present at least twice
  • ): Negative lookbehind end
  • .*?: Match 0 or more of any characters
  • \b(\w+)\b: Match and capture a word in capture group #2
  • .*\b\2\b: Make sure same word is present at least once more
Related