← Back to Blog

Regular Expressions (Regex) Tutorial for Developers

Regex can do in one line what takes twenty lines of string manipulation code. This guide covers everything from basics to lookaheads, with real patterns you will actually use.

Pankaj Kumar
Senior Software Engineer — .NET, Blazor, ASP.NET Core
4+ years building production .NET and Blazor applications. Every DevToolsHub tool and article comes from real daily development work — not documentation summaries.
Published 10 May 2026· Last reviewed Jun 2026· 8 min read · About the author →
Uses regex across .NET, JavaScript, and Python daily. Has written patterns clever enough to pass code review but confusing enough that six months later even the author needed 20 minutes to remember what they did.
Key takeaways
  • Character classes, quantifiers, anchors, and groups — the four building blocks of any regex
  • Greedy versus lazy quantifiers — why .* and .*? produce completely different matches
  • How lookaheads and lookbehinds match positions without consuming characters
  • When regex is the wrong tool: HTML parsing, JSON, and overly complex patterns
Table of Contents

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 name
  • a|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/i matches "Hello", "HELLO", "hElLo"
  • g — global: find all matches, not just the first
  • m — multiline: ^ and $ match start/end of each line
  • s — 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.
Try the free tool
Regex Tester

Test regular expressions against sample text and instantly inspect matches, groups, and indices — no login required.

Open Regex Tester