69 — Patterns: finding matches with regex
"Find all phone numbers" needs a pattern, not a fixed word. The standard
re library matches shapes: three digits, a hyphen, four digits — and
anything that looks like an email address.
Steps
\dmatches any digit and{3}means exactly three, so\d{3}-\d{4}is three digits, a hyphen, four digits.re.findallreturns every match:
run it →import re text = "Call 010-1234-5678 now" phones = re.findall(r"\d{3}-\d{4}", text) show phones['010-1234']- An email is one-or-more allowed characters,
@, then one-or-more more.+means one or more; brackets list the allowed characters:
run it →import re text = "Write to [email protected] or [email protected]" emails = re.findall(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+", text) show emails - Create a small file of contacts:
Mina 010-1234-5678 [email protected] Jun 010-9876-5432 [email protected] Office 02-3456-7890 [email protected] - The full program reads the file with
open(...).read(). Thetry/exceptfrom guide 68 reports a missing file:
run it →# contacts.nme — find phone numbers and emails in a text file. # Run: nme r contacts # re.findall searches a whole file with one pattern. import re ask file_name, "Text file to scan (for example contacts.txt): " try: text = open(file_name).read() except FileNotFoundError: show f"{file_name} is not in this folder." else: phones = re.findall(r"\d{3}-\d{4}", text) emails = re.findall(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+", text) show f"Found {len(phones)} phone numbers:" for phone in phones: show f" {phone}" show f"Found {len(emails)} email addresses:" for email in emails: show f" {email}" both = 0 for line in text.splitlines(): if re.search(r"\d{3}-\d{4}", line) and re.search(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+", line): both = both + 1 show f"{both} of {len(text.splitlines())} lines have both a phone and an email." - Run it:
printf 'contacts.txt\n' | nme r contactsText file to scan (for example contacts.txt): Found 3 phone numbers: 010-1234 010-9876 456-7890 Found 3 email addresses: [email protected] [email protected] [email protected] 3 of 3 lines have both a phone and an email. re.findallcollects every match in the text.re.search(pattern, line)answers one yes/no — it returns a match object orNone— which is how the program counts lines that have both.
Try it yourself
Add a row with a second phone style and widen the pattern, or search for a
name like Mina. Report lines that have a phone but no email.
What you learned
import reloads the standard regular-expression library.re.findall(pattern, text)returns every match in the text as a list.\dis any digit,{3}means exactly three, and+means one or more.re.search(pattern, line)tests one line and returnsNonewhen there is no match.