What Is Regex (Regular Expressions)?

Whenever you want to find, validate or replace the parts of a text that match a particular pattern, you run into the same problem: functions that search for fixed text, such as indexOf or includes, cannot express patterns that repeat at variable length or in different forms. To check whether an email address, phone number or IP address is in a valid format, you need to define a rule rather than a fixed string. Regex (regular expression) does exactly that: it is a mini language, a small syntax in its own right, used to describe character sequences.

Regex works with the same basic logic in almost every programming language (JavaScript, PHP, Python, Java) and in many tools (text editors, command line utilities, database queries). The syntax differs slightly from language to language, but core concepts such as character classes, quantifiers and groups are shared. In this guide we take JavaScript's built-in RegExp engine as our basis; that engine behaves the same way in the browser and in Node.js.

The Basic Building Blocks of Regex

A regex pattern is made up of a few basic building blocks. Understanding them one by one makes a pattern that looks complicated at first glance readable.

ConstructWhat It DoesExample
Character classesMatches a specific set of characters: <code>\d</code> a digit, <code>\w</code> a letter/digit/underscore, <code>\s</code> a whitespace character. Their uppercase forms (<code>\D</code>, <code>\W</code>, <code>\S</code>) match the opposite, that is, characters not in that set.<code>\d{3}</code> exactly 3 digits
Custom character classesInside square brackets you define your own set; with a leading <code>^</code> it matches everything outside the set.<code>[aeiou]</code> vowels, <code>[^0-9]</code> non-digits
QuantifiersState how many times the preceding element repeats: <code>*</code> zero or more, <code>+</code> one or more, <code>?</code> zero or one, <code>{n,m}</code> between n and m.<code>\d{2,4}</code> 2 to 4 digits
AnchorsPoint at a position without consuming a character: <code>^</code> the start of the text, <code>$</code> the end of the text, <code>\b</code> a word boundary.<code>^\d+$</code> digits only, from start to end
GroupsParentheses let you treat several characters as a single unit and apply a quantifier to them; <code>(?:...)</code> is a non-capturing group.<code>(ab)+</code> ab, abab, ababab...
AlternationThe vertical bar matches one of several options.<code>cat|dog</code>

Flags: g, i, m, s

Flags appended to the end of a regex pattern change the engine's behaviour. The g (global) flag finds all matches in the text rather than only the first one; without this flag, .exec() in JavaScript always returns just the first result. i (case-insensitive) ignores the difference between uppercase and lowercase. With m (multiline) on, the ^ and $ anchors match the start and end of each line in the text instead of the start/end of the whole text. With s (dotAll) on, the . wildcard, which normally does not match the line break character (\n), covers line breaks too.

JavaScript's built-in RegExp engine (the ECMAScript standard) does not support some advanced features found in PCRE, used in PHP or Perl, or in Python's re module; for example there are no recursive patterns or conditional expressions. Lookbehind ((?<=...) and (?<!...)) is now supported in modern browsers, but if you are going to run the same pattern in a different language or an older environment, it is worth keeping this portability difference in mind.

Regex Through Real Examples

The three examples below show scenarios you meet often in everyday development work.

  • A simple email-like pattern: the pattern \b\w+@\w+\.\w+\b captures text made up of a username, an @ sign and a domain name containing a dot. Remember that this is not real RFC 5322 email validation, only a practical approximation — to verify that an email address really exists, a separate confirmation step (a verification email) should be used on the server side.
  • Extracting only the digits: the pattern /\d+/g finds all groups of digits in a text; for example, to strip separators, spaces and parentheses out of a phone number field and keep only the digits, you can use text.replace(/\D/g, '') (\D matches every non-digit character).
  • Trimming leading/trailing whitespace: the pattern /^\s+|\s+$/g captures whitespace characters (space, tab, line break) at the start or end of the text; replacing them with an empty string is the manual, regex-based reimplementation of the String.prototype.trim() method.

Mistakes Beginners Make Most Often

  • Confusing greedy and lazy quantifiers: *, + and {n,m} are greedy by default, meaning they try to take the longest matching sequence. In an HTML-like text, the pattern <.+> can swallow everything between the first < and the last > as a single match. Adding a ? at the end (<.+?>) makes the quantifier lazy so it finds the shortest possible match.
  • Forgetting to escape special characters: characters such as . * + ? ( ) [ ] { } ^ $ | carry a special meaning in regex. If you write 19.99 while searching for the dot in a price (19.99), the dot means "any character"; to search for a real dot you have to write 19\.99 and cancel its special meaning with a backslash.
  • Catastrophic backtracking: nested quantifiers (a pattern such as (a+)+b, for instance) can make the engine try thousands of possible combinations on non-matching input, causing processing time to grow exponentially. This is a real performance risk (ReDoS) that can temporarily lock up a web page or a server-side service, which is why patterns that work on external input in particular need to be designed carefully.
  • Forgetting to use anchors: when you want to verify that a value is entirely in a specific format from start to end, if you do not add the ^ and $ anchors the pattern also reports "valid" whenever it finds a partial match anywhere in the text. For example ^\d{5}$ accepts only a string consisting of exactly 5 digits, while the unanchored \d{5} also finds a match inside a string such as "abc12345xyz".

Test Your Pattern Safely

When writing a regex pattern, trying it first against small, realistic test data lets you see how many matches are found, what the capture groups return and how your pattern behaves on unexpected input before it goes to production. KEYDAL's regex test tool applies the pattern you write to a sample text in real time, highlights the matches and lists the capture groups separately — all in your browser, with no data sent to a server.