What is a regular expression?
A regular expression (regex or regexp) is a sequence of characters that defines a search pattern. Regex engines are built into virtually every programming language and text editor. They are used to search, validate, extract, and transform text — finding all email addresses in a document, validating a phone number format, or replacing date formats in batch processing.
Literal characters and the dot
The simplest regex is a plain string: hello matches the literal text "hello" wherever it appears. The dot . is special — it matches any single character except a newline: h.llo matches "hello", "hallo", "h1llo", etc.
Character classes
Square brackets define a set of characters to match:
[aeiou]— matches any single vowel[a-z]— matches any lowercase letter[A-Za-z0-9]— matches any alphanumeric character[^0-9]— the caret inside brackets negates: matches anything that is NOT a digit
Shorthand character classes save typing:
\d— any digit:[0-9]\D— any non-digit:[^0-9]\w— any word character:[A-Za-z0-9_]\W— any non-word character\s— any whitespace (space, tab, newline)\S— any non-whitespace
Quantifiers
Quantifiers specify how many times the preceding element must match:
*— zero or more times+— one or more times?— zero or one time (makes the element optional){3}— exactly 3 times{2,5}— between 2 and 5 times (inclusive){2,}— 2 or more times
By default quantifiers are greedy — they match as many characters as possible. Append ? to make them lazy (match as few as possible): .*?
Anchors
^— matches the start of the string (or line in multiline mode)$— matches the end of the string (or line in multiline mode)\b— word boundary: position between a word character and a non-word character\B— not a word boundary
Example: ^\d{4}$ matches a string that is exactly four digits — no more, no less.
Groups and capturing
(abc)— capturing group: matches "abc" and captures it for later use(?:abc)— non-capturing group: groups without capturing (better performance when you do not need the capture)(?<name>abc)— named capturing group: access the match by namea|b— alternation: matches either "a" or "b"
Lookaheads and lookbehinds
Lookarounds match a position without consuming characters:
(?=...)— positive lookahead: position followed by the pattern(?!...)— negative lookahead: position NOT followed by the pattern(?<=...)— positive lookbehind: position preceded by the pattern(?<!...)— negative lookbehind: position NOT preceded by the pattern
Example: \d+(?= USD) matches a number only when followed by " USD", without including " USD" in the match.
Flags
i— case-insensitive:/hello/imatches "Hello", "HELLO", "hElLo"g— global: find all matches, not just the firstm— multiline:^and$match start/end of each lines— dot-all: makes.match newlines too
Useful real-world patterns
- Email (basic):
^[^\s@]+@[^\s@]+\.[^\s@]+$ - URL:
https?://[\w\-]+(\.[\w\-]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])? - Date (YYYY-MM-DD):
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$ - Indian mobile number:
^[6-9]\d{9}$ - IPv4 address:
^(\d{1,3}\.)\{3}\d{1,3}$ - Hex colour:
^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$ - Trim whitespace: replace
^\s+|\s+$with empty string
When NOT to use regex
Regex is powerful but not the right tool for every job:
- Parsing HTML or XML — use a proper parser (HtmlAgilityPack, BeautifulSoup). Nested tags break regex-based approaches.
- Parsing JSON — always use a JSON parser, never regex.
- Email validation in production — a basic regex catches obvious mistakes, but the only reliable way to validate an email is to send a confirmation message to it.
- Overly complex patterns — if your regex is longer than 60 characters and has more than three groups, consider whether a small parser would be clearer and more maintainable.