keepcalculator

06 Numbers and Powers

Regex Basics: Patterns for Finding, Extracting & Cleaning Text

Card No. 06·21434 · Updated · Standard formula, shown below

Regex (regular expressions) is a pattern-matching language that lets you find, extract, and clean text by describing what you’re looking for instead of searching for exact strings. This article explains the core concepts—literal characters, metacharacters, character classes, quantifiers, anchors, groups, and alternation—with practical examples you can apply immediately in tools like grep, Python, JavaScript, or your text editor.

What Is Regex and Why Does It Matter?

Regular expressions are a sequence of characters that define a search pattern. They originated in formal language theory in the 1950s and became widely used in Unix tools like grep and sed. Today, every major programming language and most text editors support regex. The power comes from its ability to match variable text—for example, finding all phone numbers in a document regardless of the exact digits, or extracting every email address from a log file.

Regex is not a programming language itself; it’s a pattern syntax that you embed in a host language. The same pattern like \d{3}-\d{3}-\d{4} works in Python, JavaScript, and even in the search bar of VS Code (with slight variations). Learning regex once saves you hours of manual searching and cleaning.

Core Building Blocks: Literals and Metacharacters

Every regex is built from two types of characters:

  • Literals—match themselves exactly. The pattern cat matches the substring “cat” anywhere in a string.
  • Metacharacters—have special meaning. The most important are: . ^ $ * + ? { } [ ] \ | ( ). To match a literal metacharacter, escape it with a backslash, e.g., \. matches a period.

The dot . is the wildcard—it matches any single character except a newline. So c.t matches “cat”, “cot”, “cut”, and even “c3t”. The backslash \ is used to escape metacharacters and also to introduce shorthand classes:

  • \d – any digit (0-9)
  • \w – any word character (letter, digit, underscore)
  • \s – any whitespace (space, tab, newline)
  • \D, \W, \S – the negated versions (non-digit, non-word, non-whitespace)

Example: \d{3} matches exactly three digits in a row.

Character Classes: Matching a Set of Characters

Square brackets [ ] define a character class—a set of characters where any one can match. For instance:

  • [aeiou] matches any single vowel.
  • [a-z] matches any lowercase letter.
  • [0-9] is equivalent to \d.
  • [^0-9] matches any character that is NOT a digit (the caret negates the class).

Character classes are useful for cleaning text where you want to allow variations. For example, to match a US ZIP code with or without the +4 extension: \d{5}(-\d{4})?—the ? makes the group optional.

Quantifiers: How Many Times Something Matches

Quantifiers specify repetition. The most common are:

  • * – zero or more times (e.g., ab*c matches “ac”, “abc”, “abbc”)
  • + – one or more times (ab+c matches “abc” but not “ac”)
  • ? – zero or one time (colou?r matches both “color” and “colour”)
  • {n} – exactly n times (\d{4} matches four digits)
  • {n,} – at least n times
  • {n,m} – between n and m times

By default, quantifiers are greedy—they match as much as possible. In <.+> applied to <b>bold</b>, it matches the whole string because it starts at the first < and ends at the last >. To make it lazy (match as little as possible), add a ? after the quantifier: <.+?> matches only <b>.

Anchors and Word Boundaries: Positioning Your Match

Anchors don’t match characters; they match positions:

  • ^ – start of a line/string (in multiline mode, start of each line)
  • $ – end of a line/string
  • \b – word boundary (between a word character and a non-word character)
  • \B – not a word boundary

Example: ^\d{3}$ matches a string that consists of exactly three digits and nothing else. \bcat\b matches the word “cat” but not “category” or “concatenate”.

Groups and Alternation: Capturing and Choosing

Parentheses ( ) serve two purposes: grouping and capturing. Grouping lets you apply quantifiers to a whole subpattern, e.g., (ab)+ matches “ab”, “abab”, “ababab”. Capturing also saves the matched text for later use—in replacement, you can refer to \1 (or $1 in some languages) for the first group.

Alternation | is like an OR operator. cat|dog matches either “cat” or “dog”. Combine with grouping to limit scope: (cat|dog)s? matches “cat”, “cats”, “dog”, “dogs”.

Non-capturing groups (?:...) group without capturing—useful when you don’t need to extract the value, saving memory and keeping your backreference numbering clean.

Practical Examples: Finding, Extracting, Cleaning

Here are concrete patterns you can adapt:

  • Extract all email addresses: [\w.+-]+@[\w-]+\.[\w.-]+ (simplified; real-world emails have more complex rules).
  • Find dates in MM/DD/YYYY format: \b(0?[1-9]|1[0-2])/(0?[1-9]|[12]\d|3[01])/(19|20)\d\d\b.
  • Remove HTML tags: In a text editor, replace <[^>]+> with an empty string.
  • Clean extra whitespace: Replace \s+ with a single space.
  • Validate a simple password (at least 8 chars, one letter, one digit): ^(?=.*[A-Za-z])(?=.*\d).{8,}$ using lookaheads.

Note that lookaheads ((?=...)) and lookbehinds ((?<=...)) are advanced features not supported in all flavors (e.g., JavaScript didn't support lookbehind until ES2018).

Common Pitfalls and How to Avoid Them

  • Forgetting to escape characters like . or * when you want a literal. In example.com, the dot must be escaped as example\.com.
  • Greedy vs. lazy matching—as shown above, always consider whether you need .*? instead of .*.
  • Using regex for non-regular languages—parsing HTML or JSON with regex is fragile. Use a proper parser for those.
  • Ignoring multiline mode—the ^ and $ behave differently with m flag. In Python, use re.MULTILINE.
  • Backreference numbering—if you add or remove groups, renumber carefully.

Regex Flavors and Tools

Not all regex is identical. The main flavors are POSIX (basic and extended), Perl-compatible (PCRE), and the simpler versions in JavaScript and Python. Differences include:

  • Lookbehind support (PCRE and Python support it, JavaScript only recently).
  • Named groups syntax: Python uses (?P<name>...), PCRE uses (?<name>...).
  • Unicode handling—\w may or may not match accented characters depending on the flavor.

When in doubt, test your pattern in an online regex tester like regex101.com (which allows you to switch flavors) before deploying it in code.

Frequently Asked Questions

How do I match a literal backslash?

Use a double backslash \\ in your regex pattern. In many programming languages, you need to escape again for the string literal, so in Python you'd write "\\\\" to match a single backslash.

What's the difference between \d and [0-9]?

In most flavors, \d matches any Unicode digit (e.g., Arabic-Indic digits) while [0-9] matches only ASCII digits. If you want only ASCII, use [0-9].

How do I make a regex case-insensitive?

Use the i flag: in Python re.IGNORECASE, in JavaScript /pattern/i, and in many editors there's a case-insensitive toggle.

Can I use regex to parse HTML?

Generally no. HTML is not a regular language; regex will fail on nested tags and malformed markup. Use an HTML parser like BeautifulSoup (Python) or DOMParser (JavaScript).

Why does my regex work in one tool but not another?

Different engines have different features and defaults. For example, JavaScript doesn't support lookbehind in older versions, and some tools don't support \d in POSIX mode. Always check the documentation for your specific tool.

How do I extract text between two markers?

Use a lazy quantifier: START(.*?)END with the s flag (dot matches newline) if the text spans multiple lines. For example, <title>(.*?)</title> extracts the title content.

Related

Method: the standard formula for this calculation, rounded as each result states. See how the calculators work or report an error.

More cards in this drawer

The whole Numbers and Powers drawer →