13 d up · CPU 17% · RAM 44% · Storage 20% All systems operational 99.79% uptime (30 days) View status →
Guides

Regular expressions for beginners

A regular expression (regex) is a pattern you use to search text: all the IP addresses in a log file, the lines that start with a date, or the numbers in a long message. At first it looks like a cat walked across the keyboard, but with a handful of building blocks you get a long way. Try everything out in the Regex Tester as you go, which shows live what is found.

The building blocks

Ordinary letters and digits search for themselves: cat finds “cat”. Special characters give you more power:

Characters

Any character (except a newline) .
A digit \d
A letter, digit or underscore \w
A space, tab or newline \s
One of these characters [abc]
A character from a range [a-z]
Anything except these characters [^abc]
A real dot (escaping a special character) \.

How many times?

Zero or more times *
One or more times +
Zero or one time (optional) ?
Exactly three times {3}
Between one and three times {1,3}

Position and groups

Start of the line ^
End of the line $
Word boundary \b
A group (and remember the part found) (abc)
A group without remembering (?:abc)
This or that cat|dog

Building a pattern step by step

Say you want to find a date like 2026-10-28. Build it in small steps:

  1. A year is four digits: \d{4}
  2. Then a dash: -
  3. Month and day are two digits each: \d{2}-\d{2}

Together: \d{4}-\d{2}-\d{2}. If you only want lines that start with a date, put a ^ in front.

Examples from the admin’s life

What are you looking for? Pattern
An IPv4 address (rough) \b(?:\d{1,3}\.){3}\d{1,3}\b
A MAC address (?:[0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}
A date (yyyy-mm-dd) \d{4}-\d{2}-\d{2}
Lines with “error” or “warning” error|warning
A port number after a colon :(\d{1,5})\b
Empty lines ^$

The IPv4 pattern is rough: it also finds 999.999.999.999. For finding addresses in a log that’s fine. For validating input, a regex isn’t the best tool.

Greedy and lazy

By default * and + are greedy: they take as much as possible. In the text <b>one</b> and <b>two</b>, <b>.*</b> finds everything from the first <b> to the last </b>. Put a question mark after it, <b>.*?</b>, and it works lazily and you find each piece separately.

Regex on the command line

With grep you apply a pattern to a file. Which syntax works depends on the option:

grep -E "error|warning" /var/log/syslog        # extended syntax
grep -E "[0-9]{1,3}(\.[0-9]{1,3}){3}" access.log   # IP addresses
grep -P "\d{4}-\d{2}-\d{2}" app.log               # Perl syntax, with \d

Note: \d works in grep -P but not in grep -E. Use [0-9] or [[:digit:]] there. You can put a command together with an explanation per part using the grep builder, and make special characters in text safe for JSON, shell or regex with Escape and unescape.

Different programs (grep, JavaScript, Python, sed) use slightly different variants of regex. The basics above work everywhere, but always test the pattern in the program you actually use.

Common mistakes

  • Not escaping a dot. 192.168.1.1 also finds 192x168y1z1. Write 192\.168\.1\.1.
  • Too greedy. .* often takes more than you want. Try .*? or an excluded character: [^"]* finds everything up to the next quotation mark.
  • No anchor. Without ^ and $ a pattern also finds a piece in the middle.
  • Complicated patterns for an email address or URL. They quickly become unreadable and still aren’t watertight. For input validation, use your programming language’s function.
  • Nested repetitions such as (a+)+. On long text they can become extremely slow (“catastrophic backtracking”). Keep patterns simple.

In short

  • Build a pattern from small pieces and test each piece.
  • \d, \w, . and [...] say what, *, +, ? and {n} say how many times.
  • ^ and $ fix where.
  • Test in the Regex Tester before you put it in a script.