You can use
m = re.search(r'(\bgpa[ :]+)?(\d+(?:\.\d+)?)[/\d. ]{0,6}(?(1)| *gpa\b)', text, re.I)
if m:
print(m.group(2))
See the regex demo.
Details:
(\bgpa[ :]+)?
- an optional capturing group with ID 1: a whole word gpa
(case insensitive search is enabled via re.I
) and then one or more spaces or colons
(\d+(?:\.\d+)?)
- Capturing group 2: one or more digits followed with an optional sequence of a dot and one or more digits
[/\d. ]{0,6}
- zero to six /
, digits, dots or spaces
(?(1)| *gpa\b)
- If Group 1 matches, match an empty string, else, match zero or more spaces and a whole word gpa
.
See a Python demo:
import re
texts = ['GPA 3.75/4.00','GPA 3.75/4.0','GPA 3.75 /4.0','GPA 3.75 / 4.0','GPA 3.7 / 4 aaa','Major GPA: 3.6/4.0','GPA 3.1','GPA 3','some text GPA 3','3.25/4.0 GPA','some text 3.26 / 4.0 GPA','Minor in Art and Technology - 3.5/4.0 GPA aaaa','Minor in Art and Technology - 3.5 / 4.3 GPA aaaa']
rx = re.compile(r'(\bgpa[ :]+)?(\d+(?:\.\d+)?)[/\d. ]{0,6}(?(1)| *gpa\b)', re.I)
for text in texts:
m = rx.search(text)
if m:
print(text, "=>", m.group(2), sep=" ")
This outputs:
GPA 3.75/4.00 => 3.75
GPA 3.75/4.0 => 3.75
GPA 3.75 /4.0 => 3.75
GPA 3.75 / 4.0 => 3.75
GPA 3.7 / 4 aaa => 3.7
Major GPA: 3.6/4.0 => 3.6
GPA 3.1 => 3.1
GPA 3 => 3
some text GPA 3 => 3
3.25/4.0 GPA => 3.25
some text 3.26 / 4.0 GPA => 3.26
Minor in Art and Technology - 3.5/4.0 GPA aaaa => 3.5
Minor in Art and Technology - 3.5 / 4.3 GPA aaaa => 3.5