There is no way to build such regex with only ERE (extended regex).
The closer with GNU grep (perl regex) (which match 3 or more repeated characters) is:
grep -P '(\w)(((?!\1)\w)*\1){2}' filename
So, removing words with 4 or more repeats, you will get an answer:
grep -P '(\w)(((?!\1)\w)*\1){2}' filename |
grep -Pv '(\w)(((?!\1)\w)*\1){3}'
An alternative with GNU awk is:
awk '{
a=$1;
while (length(a)){
b=gensub(substr(a,0,1),"","g",a);
if(length(a)-length(b)==3){print $0;next};
a=b
}
}' filename
It works by removing all repeats of the first character, if the removal was of 3 characters then print it, else, remove the next first letter until there are no more characters to replace (an improvement is to test only if the remaining length is equal or bigger than the repeat required).
Assuming that you want to count A
as equivalent to a
, then filter your file with:
cat /usr/share/dict/words | tr [[:upper:]] [[:lower:]] > words
The two solutions are similar but not equal. The two differ on words like independence
from the dictionary file generated above.
Yes, independence
contains 3 n
's but 4 e
's. Depending of which is found first the word may be included or not. Awk solution is stable and will include words in which any character is repeated exactly 3 times. A regex solution is more slipery and will match in some conditions and not in others.
Additionally, the regex will match only word characters which do not include '
(and the file contains several words with that character).
In all, the number of lines matched is (1527 more with awk):
13758 awklist
12231 greplist
And, removing the '
(184 more with awk):
9236 awklist2
9052 greplist2
Should tastelessness teleconferencing teletypewriter teletypewriters tempestuousness timelessness tintinnabulation tintinnabulations tirelessness transcontinental transgressors transubstantiation
(just to list a few) be rejected?
All do have exactly 3 of one character and four (or more) of another.