Fall 2026
  • Discord
  • Gradescope
  • Syllabus

On this page

  • Start
  • An Initial Inspection
  • The Reviewer’s Index
  • A Usable Contact Field
  • The Edited Packet
  • Submit
  • Grading Rubric

Lab: Redacted

Due: Wednesday, November 18 at 11:59pm (one week after it is assigned) · Worth: 4 points

A reviewer needs the contacts and links in a fictional support-ticket packet, plus a copy with email addresses, Social Security numbers, and card numbers masked. Write twelve regex helpers in lab_regex.py; the supplied review_packet.py assembles their results. The reading covers the patterns, which also appear in the docchat project’s grep tool.

Meme titled 'How to write a regular expression': a photo of a cat walking across a keyboard. The resulting keysmash is, statistically, already a valid pattern.

Test patterns against real examples, including ones that should fail. On regex101.com, select the Python flavor and check every highlighted match before using a pattern in your code. Plausible-looking patterns, including LLM suggestions, can match the wrong text.

Starter repository: github.com/rtealwitter/lab-regex

Start

Select Use this template, create lab-regex under your account, and clone it. Open support_tickets.json: its fictional records separate message, contact, and card fields. Complete the helpers using their docstrings and doctests, checking one function at a time:

$ python3 -m doctest lab_regex.py

Silence means success; failures show Expected and Got. Write patterns as raw strings, such as r"\d+". The driver is ungraded practice; if an unfinished helper returns None, it stops with the helper’s name and expected type.

An Initial Inspection

An order number, phone number, and card all contain digits. Implement these three ways of inspecting a message:

Run the inspection stage:

$ python3 review_packet.py --stage inspect

For demo-001, check has_digit is true, numbers begins with "42" and "2", and the masked message begins Order XX needs X replacements.

Meme: the three-way Spider-Man pointing meme, the three Spider-Men labeled re.search, re.findall, and re.sub, all pointing at the same raw string r"\d+".

The Reviewer’s Index

Complete find_phone_numbers, area_code, find_urls, find_hashtags, and find_mentions. Use capture groups to return only the requested portion of a match, and preserve duplicates and order:

>>> find_hashtags('Big rally tonight! #MAGA #America #MAGA')
['MAGA', 'America', 'MAGA']

Check the index:

$ python3 review_packet.py --stage index

The first ticket has two phone numbers and the tags shipping, review, shipping. Its email, ada@example.com, also contains an @ followed by word characters. Inspect what your mention pattern extracts there: passing the doctests does not settle every boundary case. Investigating this match is practice; keep the required behavior specified in lab_regex.py.

Meme: a triumphant gold miner holding one gleaming nugget over a mountain of dirt, captioned “when re.findall finally returns something that isn’t [].”

A Usable Contact Field

Implement is_valid_email to check the entire contact field. Finding an email somewhere in it is insufficient:

>>> is_valid_email('ada@example.com')
True
>>> is_valid_email('ada@example.com and some extra text')
False

The reading explains ^ and $ anchors and re.fullmatch. Remember that $ can match just before a final newline; fullmatch requires the whole string.

The two-astronaut 'always has been' meme. One astronaut, looking down at a pattern, realizes 'wait, it is all anchors?'; the second, gun raised, replies 'always has been.' One is the start-anchor, the other the end-anchor.

Check the two contacts:

$ python3 review_packet.py --stage validate

demo-001 should be valid and demo-002 invalid.

The Edited Packet

Implement redact_emails, redact_ssns, and mask_last_four using re.sub. Replace emails with [REDACTED] and SSNs with XXX-XX-XXXX. For a sixteen-digit card, preserve the last four digits and mask the rest with stars. The driver passes only the card field to mask_last_four.

>>> redact_ssns('SSN 123-45-6789 on file')
'SSN XXX-XX-XXXX on file'

Check the edited records, then the complete report:

$ python3 review_packet.py --stage redact
$ python3 review_packet.py

The first card should become ************5678; both SSNs should become XXX-XX-XXXX. Check that email addresses are replaced while phone numbers, links, and ordinary text remain. Only the report’s edited fields have been redacted; the index and inspection retain the originals.

Meme: a document with a thick black bar over every single line, captioned “my search history, now GDPR-compliant thanks to re.sub.”

A pattern misses any format it does not recognize. Try SSN 000 12 3456, 909.555.0101, an empty string, and an email followed by a newline in the relevant helpers. Use these ungraded cases to identify gaps before broadening a pattern.

Submit

Rerun python3 -m doctest lab_regex.py and fix any failures. Commit and sync lab_regex.py, then submit your lab-regex repository and branch through Gradescope’s GitHub option. The first lab has the submission steps.

Meme: 'When do you finally master regular expressions?' answered by 'That is the neat part. You do not.' You will know your doctests pass the same way, the terminal simply goes quiet.

Grading Rubric

Gradescope checks each item separately and adds the points earned.

Total: 4 points.