All subjects · Computer Science · WCP04 Advanced Practical Programming and Problem-solving
Regular expressions: finding and validating text
Edexcel IAL Computer Science · WCP04 Advanced Practical Programming and Problem-solving
A regular expression (regex) is a pattern that describes text. With Python's `re` module you can find every phone number in a document, or check that a date is in the right format, in one line.
The building blocks
| Pattern | Matches |
|---|---|
| `.` | any character except newline |
| `\d` / `\D` | a digit / a non-digit |
| `\w` / `\W` | a word character (letter, digit, underscore) / anything else |
| `\s` / `\S` | whitespace / non-whitespace |
| `[abc]`, `[a-z]`, `[A-Z0-9]` | one character from the set or range |
| `[0-9]` | one character NOT in the set |
| `*` `+` `?` | 0 or more, 1 or more, 0 or 1 of the item before |
| `{3}` `{2,4}` | exactly 3, from 2 to 4 of the item before |
| `a|b` | a or b |
| `( )` | a group |
| the caret and `$` | start and end of the string |
| `\b` | a word boundary |
| `\.` | a literal full stop (a backslash escapes a metacharacter) |
The re functions
Write patterns as raw strings, r"...", so Python does not treat the backslashes itself.
re.search(p, s): the first match anywhere, as a Match object, or None.re.match(p, s): a match only at the start.re.fullmatch(p, s): the whole string must match; use it for validation.re.findall(p, s): a list of all matching strings (if the pattern has one group, the list holds the group's text).re.sub(p, new, s): replace every match.re.split(p, s): split wherever the pattern matches.- A Match object has
.group()(the text),.start()and.end()(the index of the first character, and one past the last).
import re
text = "Order 66 shipped 12-03-25; order 7 shipped 01-04-25."
print(re.findall(r"\d+", text))
m = re.search(r"\d\d-\d\d-\d\d", text)
print(m.group(), m.start(), m.end())
print(re.sub(r"\d", "#", "PIN 4821"))
print(re.split(r"[,;]\s*", "red, green;blue"))Output:
['66', '12', '03', '25', '7', '01', '04', '25']
12-03-25 17 25
PIN ####
['red', 'green', 'blue']Validating input
Build validation patterns from small, tested parts. A day from 01 to 31 is: 0 then 1 to 9, or 1 or 2 then any digit, or 3 then 0 or 1. With fullmatch, nothing extra is allowed before or after.
import re
DAY = r"(0[1-9]|[12][0-9]|3[01])"
MONTH = r"(0[1-9]|1[0-2])"
DATE = DAY + "-" + MONTH + r"-\d{2}"
for d in ["07-11-26", "31-12-25", "32-01-25", "7-11-26"]:
print(d, re.fullmatch(DATE, d) is not None)Output:
07-11-26 True
31-12-25 True
32-01-25 False
7-11-26 FalseA regex checks format only: '31-02-25' passes the pattern even though 31 February does not exist. Check ranges and real dates in code if needed. The sample mark scheme gives no credit for a day pattern that simply lists 01|02|...|31: build it from character classes as above.
What the PLS lists, and how Python writes it
- The PLS lists only four re functions:
findall,search,splitandsub.re.match,re.fullmatchand the Matchgroup()method are standard Python, so you may use them, but a question written within the PLS will validate withsearchand anchors. - To validate a whole string with
search, anchor the pattern:\A(start of string) and\Z(end of string) are both in the PLS. The caret and$also work, but$also matches just before a final newline, so '1234\n' would pass a check built with it. - The PLS lists
startandendas attributes of a match, but in Python they are methods: writem.start()andm.end()with brackets. Without brackets you get the method itself, not a number. - The PLS reminds you that
\band\Bneed a raw string: in a normal string, Python turns\binto a backspace character.
import re
PIN = r"\A\d{4}\Z"
for pin in ["1234", "12345", "1234\n"]:
print(repr(pin), re.search(PIN, pin) is not None, re.search(r"^\d{4}$", pin) is not None)
m = re.search(r"\d+", "Room 101")
print(m.start(), m.end(), callable(m.start))Output:
'1234' True True
'12345' False False
'1234\n' False True
5 8 TrueWorked example
Extract every UK-style postcode area code (one or two capital letters followed by one or two digits, as a whole word) from a sentence.
- ```python import re s = "Depots in M1, LS12 and EH3, not in 12AB." print(re.findall(r"\b[A-Z]{1,2}\d{1,2}\b", s)) ```
- Output: ``` ['M1', 'LS12', 'EH3'] ```
Answer: `[A-Z]{1,2}` then `\d{1,2}`, wrapped in word boundaries so '12AB' does not match.
Check yourself
- What does this program print?
```python
import re
print(re.findall(r"\d+", "3 cats, 12 dogs, 150 fish"))
```
Show answer
['3', '12', '150']. `\d+` matches each run of digits. Output: `['3', '12', '150']`
- What does this program print?
```python
import re
m = re.search(r"[A-Z]\d", "abc X9 Y7")
print(m.group(), m.start())
```
Show answer
X9 4. The first capital letter followed by a digit is X9, starting at index 4 (a=0, b=1, c=2, space=3). Output: `X9 4`
- What does this program print?
```python
import re
for s in ["AB123", "AB12", "ab123"]:
print(re.fullmatch(r"[A-Z]{2}\d{3}", s) is not None, end=" ")
```
Show answer
True False False. Only AB123 has exactly two capitals then three digits. Output: `True False False`
- What does this program print?
```python
import re
print(re.sub(r"\s+", " ", "too many spaces"))
```
Show answer
too many spaces. Every run of whitespace is replaced by one space. Output: `too many spaces`
- What does this program print?
```python
import re
print(re.split(r"\d", "a1b22c"))
```
Show answer
['a', 'b', '', 'c']. Splitting on each digit gives 'a', 'b', an empty string between the two 2s, and 'c'. Output: `['a', 'b', '', 'c']`
- Which function should validate that a whole input string is a 4-digit PIN?
- `re.search(r"\d{4}", pin)`
- `re.findall(r"\d", pin)`
- `re.fullmatch(r"\d{4}", pin)`
- `re.match(r"\d", pin)`
Show answer
`re.fullmatch(r"\d{4}", pin)`. fullmatch requires the entire string to be exactly four digits.
- Which pattern matches a two-digit month from 01 to 12 and nothing else (with fullmatch)?
- `0[1-9]|1[0-2]`
- `[0-1][0-9]`
- `\d{2}`
- `[1-12]`
Show answer
`0[1-9]|1[0-2]`. 0 followed by 1 to 9, or 1 followed by 0, 1 or 2.
- What does this program print?
```python
import re
print(re.findall(r"(\w+)@", "ana@x.com, bo@y.org"))
```
Show answer
['ana', 'bo']. With one group, findall returns just the group's text: the names before each @. Output: `['ana', 'bo']`
Sources
- Pearson Edexcel International Advanced Subsidiary/Advanced Level in Computer Science specification, Issue 1 (March 2026)
- Pearson Edexcel IAL Computer Science Unit 4 Programming Language Subset (PLS)
- Pearson Edexcel IAL Computer Science sample assessment materials (Unit 3 and Unit 4)
Last updated 8 November 2026. Spotted a mistake? Tell us.