One pattern, a whole class of strings
A regular expression, or regex, is a short pattern that describes a set of strings. One pattern can fit every order number, or every log line that mentions an error. The tool grep searches text with one.
Every regular expression can be run by a finite automaton, so you already know how it works. This lesson teaches you to write patterns and to see what they cannot do.
By the end of this lesson
Note
I can write a regular expression and test it with grep.
Key words
| Word | What it means | Example |
|---|---|---|
| Regular expression | a pattern that describes a set of strings | |
| Literal | a character in a pattern that matches only itself | c |
| Quantifier | a sign that says how many times to repeat | + |
| Alternation | a choice between patterns, written | | cat|dog |
| Anchor | a sign that ties a match to the start or end of a line | ^ |
| Match | to fit a pattern exactly |
The cells students fill in are left blank in this preview.
A pattern is a few small pieces
Most characters in a pattern are literals and match themselves. A few signs are special.
A dot matches any one character. Square brackets match one character from a set or range. A star, plus or question mark repeats the piece before it. A bar chooses between two patterns, and the signs ^ and $ pin a match to the start and end of a line.
The pieces and what they match
| Pattern | Means | Matches | Does not match |
|---|---|---|---|
| c.t | c, any one character, t | cat, cot | ct, cart |
| [0-9] | one digit | 7 | a |
| ab*c | a, any number of b, then c | ac, abc, abbbc | abd |
| ba+ | b then one or more a | ba, baaa | b |
| colou?r | the u is optional | color, colour | colouur |
| cat|dog | either word | cat, dog | bird |
| ^[A-Z]{2}[0-9]{2}$ | two capitals, two digits, nothing else | AB12 | AB123 |
The cells students fill in are left blank in this preview.
grep -E searches text with a pattern
The command grep -E prints every line that contains a match for the pattern. The -E switch turns on the full set of signs above.
The Runs below pipe a few lines from printf into grep, so you can see which lines survive. Without ^ and $, a match can be anywhere in the line.
A dot matches one character
printf 'cat\ncot\ncut\ncart\n' | grep -E 'c.t'Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A question mark makes a letter optional
printf 'colour\ncolor\ncolr\n' | grep -E 'colou?r'Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Anchors and a plus for a code
printf 'A12\nB7\nC123\nD\n' | grep -E '^[A-Z][0-9]+$'Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Exactly two capitals and two digits
printf 'AB12\nAB1\nA123\nXY99\n' | grep -E '^[A-Z]{2}[0-9]{2}$'Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A dot is not a full stop
In a pattern a dot means any one character. To match a real full stop you write a backslash before it.
The first Run below uses an unescaped dot, and the second escapes it. Compare which lines come back.
An unescaped dot matches anything
printf 'report.txt\nreport_txt\nreportatxt\n' | grep -E 'report.txt'Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A backslash makes the dot literal
printf 'report.txt\nreport_txt\nreportatxt\n' | grep -E 'report\.txt'Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think a dot in a pattern means a full stop, like in a file name. It means any one character. Put a backslash before it when you want a real full stop, as in report\.txt.
A pattern cannot count without limit
A regular expression is a finite automaton in disguise, so it has finite memory. It can say "some a, then some b". It cannot say "as many a as b".
To compare the two counts you must remember the number of a, and that number has no upper limit. The next Run shows a pattern accepting lines that are not equal.
It cannot tell aab from aabb
printf 'aabb\naab\nabbb\n' | grep -E '^a+b+$'Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
The lab lexer's rules are patterns
grep -c "^\[" ~/compiler/calc.lShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Walking a pattern by hand
# Walk a pattern and a text together, one place at a time.
# '#' means one digit, '@' means one letter, anything else must match itself.
pattern = "##-@"
text = "42-x"
ok = len(pattern) == len(text)
i = 0
while ok and i < len(pattern):
p = pattern[i]
ch = text[i]
if p == "#":
ok = ch.isdigit()
elif p == "@":
ok = ch.isalpha()
else:
ok = ch == p
i = i + 1
print(ok)
# Change text to "4x-2" and run again.