Parentheses group part of a regular expression so an operator can act on that part as a unit. In Python’s `re` patterns, `(h|H)ello` matches either `hello` or `Hello`: the `|` chooses between the two letters, not between two whole words. section 16.2
A group can also be optional. In `(\d{3}-)?\d{3}-\d{4}`, `?` applies to the grouped area code and hyphen. The pattern therefore accepts a phone number with or without that prefix. The same approach makes a middle name optional in a name-and-phone record. section 16.4
Grouping is useful for extraction as well as matching. A named group uses `(?P<name>...)` to retain a field’s matched text. After `regexp.search(line)` succeeds, retrieve it with `result.group('name')`; check for a missing match before calling `group()`. An optional middle-name group yields `None` when absent. section 16.4
import re
regexp = re.compile(r"(?P<last>[-a-zA-Z]+)," #1
r" (?P<first>[-a-zA-Z]+)" #2
r"( (?P<middle>([-a-zA-Z]+)))?" #3
r": (?P<phone>((\d{3}-)?\d{3}-\d{4}))" #4
)
file = open("textfile", 'r')
for line in file.readlines():
result = regexp.search(line)
if result == None: #5
print("Oops, I don't think this is a record")
else:
last_name = result.group('last')
first_name = result.group('first')
middle_name = result.group('middle')
if middle_name == None:
middle_name = ""
phone_number = result.group('phone')
print(f"Name: {first_name} {middle_name} {last_name} Number:
{phone_number}")file.close()
See the complete name-and-phone pattern, the search check, and retrieval of the `last`, `first`, `middle`, and `phone` groups. section 16.4
Use grouping to set the scope of `|` or `?`; use named groups when you also need the matched fields. A pattern that merely finds a correctly formatted line does not, by itself, extract its data. section 16.2 section 16.4





