Reputation: 1372
How can I match all occurrences of "an Upper and Lower case" or vice versa of the same letter following each other in a string using regex? e.g: "aADFfGcCgs", I want to match aA, Ff and cC
I am doing the following re.findall('[a-Z][A-Z]', string)
which can only match two characters which are not necessarily the opposite case of the other letter.
Upvotes: 3
Views: 143
Reputation: 2596
@Wiktor Stribiżew's answer is obviously the best.
But for just showing another method(without regex),
I append code for @FoolischEx's idea.
import itertools
from string import ascii_letters
def pairwise(iterable):
"""From Itertools Recipes
https://docs.python.org/3/library/itertools.html#itertools-recipes
"""
a, b = itertools.tee(iterable)
next(b, None)
return zip(a, b)
def find_all(string: str) -> list:
return [
''.join((a, b)) for a, b in pairwise(string)
if all((
a in ascii_letters,
b in ascii_letters,
abs(ord(a) - ord(b)) == abs(ord('A') - ord('a')),
))
]
print(find_all('AaaAbBcDdD'))
output:
['Aa', 'aA', 'bB', 'Dd', 'dD']
Note that there is little difference between this and using regex.
regex output for same string:
['Aa', 'aA', 'bB', 'Dd']
Upvotes: 0
Reputation: 79
I dont think regex can check relations in patterns.
I would iterate through each char and see if the char is between 97 and 122 or 65 and 90 to see if the char is upper or lower and then check the neighboring char - or + 32.
Upvotes: 0
Reputation: 626929
You may use
print( [x.group() for x in re.finditer(r'([a-zA-Z])(?!\1)(?i:\1)', 'aADFfGcCgs')] )
# => ['aA', 'Ff', 'cC']
With re.findall
:
[x for x,y in re.findall(r'(([a-zA-Z])(?!\2)(?i:\2))', 'aADFfGcCgs')]
See the Python demo.
Details
([a-zA-Z])
- Capturing group 1: an ASCII letter(?!\1)
- the next char should not equal the letter captured in Group 1(?i:\1)
- the same char as captured in Group 1, but the pattern can match in a case insensitive way.Upvotes: 6