Python Regex return words containing double character

Viewed 316

I have a big string "a" and I want to extract all words with double characters from there. I need words as output (not lines or characters). I tried simple things like this:

re.findall(r'\b.*([A-Za-z])\1.*\b', a)

which gives a list of letters.

I also tried this:

pat='(\w*)\1'
def f(a, pat):
   pat = r'(\w*%s\w*)' % pat
   return re.findall(pat, a)
print (f(a,pat))

It gave me empty list. So I have two problems: 1) How to return words? 2) What regex to use to select words with double letters (like 'look', 'settle' etc).

3 Answers

You can try this:

import re


def find_words(text):
    words = re.findall(r'(\w*(\w)\2\w*)', text, re.IGNORECASE)
    return words

text = 'look book cat battle settle america google facebook gmail ball'
words = find_words(text=text)

for word, char in words:
    print(f'Word: {word} - Double Char: {char}')

Output:

Word: look - Double Char: o
Word: book - Double Char: o
Word: battle - Double Char: t
Word: settle - Double Char: t
Word: google - Double Char: o
Word: facebook - Double Char: o
Word: ball - Double Char: l

You can do this:

import re

def f(a):
   return [x[0] for x in re.findall(r'\b([a-z]*([a-z]+)\2[a-z]*)\b', a, re.IGNORECASE)]

print(f("We Choose To Go To The Moon"))

Which will output:

['Choose', 'Moon']

This works when there's multiple repeated letters (success) or when the repeated letters are different cases (Eel). Returns an empty array if there are no words with repeating letters.

1). The pattern you tried \b.*([A-Za-z])\1.*\b will:

  • match the first word boundary
  • then match 2 of the same chars from ranges a-z A-Z in the string
  • then match the last word boundary because .* can match any character so the whole match is not limited to a "word"

Then using re.findall will only return the capture group value, which is a single character.

2). In the pattern (\w*)\1 the quantifier for the word characters is 0 or more. It will for example match all positions as an empty string will also match, and could possible also match 2 times abc like abcabc


You can use a single capture group, and to get all the matches use re.finditer instead.

\w*([a-zA-Z])\1\w*

The pattern matches:

  • \w* Match optional word characters
  • ([a-zA-Z])\1 Match a single char from ranges a-z A-Z, followed by matching the exact same char using a backreference \1
  • \w* Match optional word characters

Regex demo | Python demo

import re

pattern = r"\w*([a-zA-Z])\1\w*"
s = 'settle, look, test'
for m in re.finditer(pattern, s):
    print(m.group())

Output

settle
look
Related