Patterns, not just words
Often you don't know the exact text, only its shape: a line that starts with Server, three digits, a dash, four digits. A regular expression (regex) describes that shape. grep understands them, and grep -E (extended) understands the full set.
cat contacts.txtIn the terminal
student@vulntech:~$ cat contacts.txt Ada Lovelace, ada@example.com, 555-0101 Grace Hopper, grace.hopper@navy.example, 555-0102 Linus, linus@kernel.example, call 555-0199 not an email: bob(at)example.com Server 10.0.0.15 is up Server 192.168.1.30 is down Order #4471 shipped order #12 cancelled
The building blocks
| Symbol | Means | Example |
|---|---|---|
^ | Start of the line | ^Server |
$ | End of the line | shipped$ |
. | Any one character | h.t matches hat, hot, h t |
[abc] | One of these characters | [Oo]rder |
[0-9], [a-z] | One character from a range | [0-9] is any digit |
[^0-9] | Any character except these | Not a digit |
* | The thing before it, 0 or more times | lo*l: ll, lol, lool |
+ | 1 or more times (-E) | [0-9]+: a number |
? | 0 or 1 time (-E) | colou?r |
{3} | Exactly 3 times (-E) | [0-9]{3} |
a|b | a or b (-E) | Ada|Linus |
\b | A word boundary: the edge of a word | \bcat\b doesn't match concat |
\. | A real dot (the backslash cancels the special meaning) | 10\.0 |
Anchors: start and end
grep '^Server' contacts.txt
grep 'shipped$' contacts.txt
grep -i '^order' contacts.txtIn the terminal
student@vulntech:~$ grep '^Server' contacts.txt Server 10.0.0.15 is up Server 192.168.1.30 is down student@vulntech:~$ grep 'shipped$' contacts.txt Order #4471 shipped student@vulntech:~$ grep -i '^order' contacts.txt Order #4471 shipped order #12 cancelled
Classes and repeats
Find phone numbers: three digits, a dash, four digits. -o prints only the part that matched instead of the whole line:
grep -E '[0-9]{3}-[0-9]{4}' contacts.txt
grep -oE '[0-9]{3}-[0-9]{4}' contacts.txtIn the terminal
student@vulntech:~$ grep -E '[0-9]{3}-[0-9]{4}' contacts.txt Ada Lovelace, ada@example.com, 555-0101 Grace Hopper, grace.hopper@navy.example, 555-0102 Linus, linus@kernel.example, call 555-0199 student@vulntech:~$ grep -oE '[0-9]{3}-[0-9]{4}' contacts.txt 555-0101 555-0102 555-0199
An email address is letters, dots and so on, an @, then a domain with a dot in it:
grep -oE '[a-z.]+@[a-z]+\.[a-z.]+' contacts.txtIn the terminal
student@vulntech:~$ grep -oE '[a-z.]+@[a-z]+\.[a-z.]+' contacts.txt ada@example.com grace.hopper@navy.example linus@kernel.example
IP addresses: four numbers separated by real dots, and alternatives with |:
grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' contacts.txt
grep -E 'Ada|Linus' contacts.txtIn the terminal
student@vulntech:~$ grep -oE '[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+' contacts.txt 10.0.0.15 192.168.1.30 student@vulntech:~$ grep -E 'Ada|Linus' contacts.txt Ada Lovelace, ada@example.com, 555-0101 Linus, linus@kernel.example, call 555-0199
Tip: Always put the pattern in single quotes. Without them, the shell treats
*,$and|as its own special characters beforegrepsees them.
Common mistake: Wildcards (module 3) and regular expressions look alike but aren't the same. In a file name,
*.txtmeans anything ending in .txt. In a regex,*means repeat the thing before me, and.means any character.
Remember:
^start,$end,.any character,[ ]one of,*+?{n}repeats. Usegrep -Eand single quotes.