Frontend Master

JavaScript Curriculum

Describing Patterns in Text
+45 XP

Describing Patterns in Text

medium
~22 min·45 XP

Nexus receives user-submitted data: usernames, emails, bio text. The validation code is a maze of indexOf() calls, split() chains, and charAt() checks — 80 lines to validate an email. Regular expressions compress that into a single pattern that's simultaneously more powerful and more readable, once you know the syntax.

What is a regular expression?

A regular expression (regex) is a pattern that describes a set of strings. Instead of writing if (str.includes('@') && str.includes('.')), you write a pattern that matches exactly the strings you want.

js
const emailPattern = /[\w.+-]+@[\w-]+\.[a-z]{2,}/i emailPattern.test('hello@nexus.app') // true emailPattern.test('not an email') // false

The /pattern/flags syntax is a regex literal — similar to how "string" is a string literal. Alternatively: new RegExp('pattern', 'flags').


The syntax building blocks

PatternMeaningExample match
.Any character except newlinea.c matches abc, axc
\dDigit (0–9)\d\d matches 42
\wWord character (a–z, A–Z, 0–9, _)\w+ matches hello_42
\sWhitespace (space, tab, newline)\s+ matches
[abc]Character class — any of a, b, c[aeiou] matches vowels
[^abc]Not any of a, b, c[^\d] matches non-digits
[a-z]Range — any lowercase letter[a-zA-Z] any letter
\bWord boundary\bcat\b matches "cat" not "cats"
^Start of string^Hello
$End of stringworld$

Quantifiers

PatternMeaning
*Zero or more
+One or more
?Zero or one (optional)
{3}Exactly 3
{2,5}Between 2 and 5
{2,}2 or more

Flags

js
/pattern/g // global — find all matches (not just first) /pattern/i // case-insensitive /pattern/m // multiline — ^ and $ match line starts/ends /pattern/gi // combine flags

Live testing — try the patterns

regex tester — live match highlighting
//
Contact us: hello@nexus.app or support@nexus.io
2 matches"hello@nexus.app""support@nexus.io"

The four string/regex methods

regex.test(string) → booleanreturns: true or false

code

const emailRe = /[\w.]+@[\w]+\.[a-z]{2,}/i

emailRe.test('hello@nexus.app')   // true
emailRe.test('not an email')       // false
emailRe.test('ADMIN@NEXUS.IO')     // true (i flag)

output

true
false
true

Use .test() when you only need yes/no — faster than .match() because it stops at the first match.


Capture groups

Parentheses create a capture group — a sub-match you can extract:

js
const dateStr = '2024-03-15' const match = dateStr.match(/(\d{4})-(\d{2})-(\d{2})/) if (match) { match[0] // '2024-03-15' — full match match[1] // '2024' — group 1 match[2] // '03' — group 2 match[3] // '15' — group 3 } // Named groups — more readable const m = dateStr.match(/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/) m?.groups?.year // '2024'

Groups in .replace():

js
// Reformat date from YYYY-MM-DD to DD/MM/YYYY '2024-03-15'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$3/$2/$1') // '15/03/2024'

Common patterns worth knowing

js
// Email (simplified) /[\w.+-]+@[\w-]+\.[a-z]{2,}/i // URL /https?:\/\/[\w.-]+(?:\/[\w./?=%&-]*)?/i // Phone (US, flexible) /\+?1?\s?[\(\-]?\d{3}[\)\-\s]?\d{3}[\-\s]?\d{4}/ // Slug (URL-safe string) /^[a-z0-9]+(?:-[a-z0-9]+)*$/ // Hex colour /#([0-9a-f]{3}|[0-9a-f]{6})\b/i // @mention /@\w+/g // Trim extra whitespace str.replace(/\s+/g, ' ').trim()
⚠️Don't use regex for HTML or deeply nested structures
Regex matches flat patterns. It can find a tag in HTML but cannot reliably parse HTML structure — use a DOM parser for that. Similarly, regex cannot match arbitrarily nested brackets like balanced parentheses. For flat string patterns, regex is the right tool.

Your challenge

@\w+ is the core pattern: @ is a literal @, \w+ matches one or more word characters (letters, digits, underscores). With the g flag, .match() returns all matches as an array. Guard against null: return text.match(/@\w+/g) ?? [] covers the no-match case neatly using the nullish coalescing operator from lesson-13.

Challenge

Write a function called extractMentions(text) that finds all @username mentions in a string. A mention is @ followed by one or more word characters (letters, digits, underscores). Use a regex with the global flag. Return the array of matches (the full @username strings), or an empty array if there are none. Test with: 'Hello @alex and @jordan_99, cc @sam!' — should return ['@alex', '@jordan_99', '@sam'].

regexregular-expressionspattern-matching.test().match().replace().split()flagscharacter-classesgroups
Describing Patterns in Text | Nexus Learn