At the Jurassic Park control center, Dennis Nedry has just received a task: search thousands of system logs for anomalies. "I'm not going to browse through this manually," he mutters. "I'll use regular expressions — the most powerful tool for finding patterns in text!"
Regular expressions (RegEx or RegExp) are patterns used to match character strings in text. They're like "search DNA" — they define exactly what we're looking for.
1// Simplest regular expression — searching for exact text
2const dinoIdPattern = /RAPTOR-d+/;
3console.log(dinoIdPattern.test("RAPTOR-001")); // true
4console.log(dinoIdPattern.test("TREX-001")); // false
5
6// Creating with the RegExp constructor
7const speciesPattern = new RegExp("Velociraptor", "i"); // i = case insensitive
8console.log(speciesPattern.test("velociraptor")); // true1// Literal notation
2const literal = /pattern/flags;
3
4// Constructor notation
5const constructor = new RegExp("pattern", "flags");
6
7// Examples
8const emailPattern = /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}/;
9const dinoIdPattern = /^[A-Z]{2,6}-d{3}$/;1const log = "2024-01-15 10:30:45 [RAPTOR-001] STATUS: escaped, SECTOR: B-4";
2
3// test() — returns true/false
4const hasEscaped = /STATUS: escaped/.test(log);
5console.log(hasEscaped); // true
6
7// match() — returns array of matches
8const dateMatch = log.match(/d{4}-d{2}-d{2}/);
9console.log(dateMatch[0]); // "2024-01-15"
10
11// matchAll() — returns all matches (with flag g)
12const allNumbers = [...log.matchAll(/d+/g)];
13console.log(allNumbers.map(m => m[0])); // ["2024", "01", "15", "10", "30", "45", "001", "4"]
14
15// replace() — replace matches
16const sanitized = log.replace(/RAPTOR-d+/g, "[REDACTED]");
17console.log(sanitized); // "... [REDACTED] STATUS: ..."
18
19// split() — split by pattern
20const parts = log.split(/[s,]+/);1// \d - any digit (0-9)
2const sectorLog = "Sector 7 - status OK";
3console.log(sectorLog.match(/\d/g)); // ["7"]
4
5// \w - word character (letter, digit, underscore)
6const code = "DINO_001_REX";
7console.log(code.match(/\w+/g)); // ["DINO_001_REX"]
8
9// \s - whitespace (space, tab, newline)
10const text = "Park\tJurassic\nStatus";
11console.log(text.split(/\s+/)); // ["Park", "Jurassic", "Status"]
12
13// . (dot) - any character (except newline)
14const pattern = /T.Rex/;
15console.log(pattern.test("T-Rex")); // true
16console.log(pattern.test("T Rex")); // true
17console.log(pattern.test("TXRex")); // true1// \D - everything except digits
2// \W - everything except word characters
3// \S - everything except whitespace
4
5const mixed = "Dino123!@#";
6console.log(mixed.match(/\D/g)); // ["D", "i", "n", "o", "!", "@", "#"]1// [abc] - one of the listed characters
2const vowels = /[aeiou]/gi;
3console.log("Tyrannosaurus".match(vowels)); // ["a", "o", "a", "u"]
4
5// [a-z] - character range
6const lowercase = /[a-z]+/g;
7console.log("T-Rex123".match(lowercase)); // ["ex"]
8
9// [^abc] - negation - everything except listed
10const notDigit = /[^0-9]+/g;
11console.log("Sector7A".match(notDigit)); // ["Sector", "A"]
12
13// Combining ranges
14const alphanumeric = /[a-zA-Z0-9]+/g;
15console.log("ID: DINO-001".match(alphanumeric)); // ["ID", "DINO", "001"]1// * - zero or more
2const pattern1 = /ro*ar/;
3console.log(pattern1.test("rar")); // true (0 times 'o')
4console.log(pattern1.test("roar")); // true (1 time 'o')
5console.log(pattern1.test("roooar")); // true (many times 'o')
6
7// + - one or more
8const pattern2 = /ro+ar/;
9console.log(pattern2.test("rar")); // false (need at least 1 'o')
10console.log(pattern2.test("roar")); // true
11
12// ? - zero or one
13const pattern3 = /colou?r/;
14console.log(pattern3.test("color")); // true (American)
15console.log(pattern3.test("colour")); // true (British)
16
17// {n} - exactly n times
18const idPattern = /DINO-\d{3}/;
19console.log(idPattern.test("DINO-001")); // true
20console.log(idPattern.test("DINO-01")); // false
21
22// {n,m} - from n to m times
23const codePattern = /[A-Z]{2,4}-\d{3,5}/;
24console.log(codePattern.test("REX-001")); // true
25console.log(codePattern.test("TREX-12345")); // true
26console.log(codePattern.test("A-1")); // false1// ^ - start of text/line
2const startPattern = /^ALERT/;
3console.log(startPattern.test("ALERT: Dinosaur escaped")); // true
4console.log(startPattern.test("Status: ALERT")); // false
5
6// $ - end of text/line
7const endPattern = /OK$/;
8console.log(endPattern.test("Status: OK")); // true
9console.log(endPattern.test("OK - done")); // false
10
11// \b - word boundary
12const wordBoundary = /\bRex\b/;
13console.log(wordBoundary.test("T-Rex")); // true
14console.log(wordBoundary.test("Rexona")); // false (Rex is not a separate word)1// () - capturing group
2const datePattern = /(\d{4})-(\d{2})-(\d{2})/;
3const date = "2024-06-15";
4const match = date.match(datePattern);
5console.log(match[0]); // "2024-06-15" (full match)
6console.log(match[1]); // "2024" (first group)
7console.log(match[2]); // "06" (second group)
8console.log(match[3]); // "15" (third group)
9
10// | - alternative (or)
11const dinoPattern = /T-Rex|Velociraptor|Triceratops/;
12console.log(dinoPattern.test("T-Rex spotted")); // true
13console.log(dinoPattern.test("Velociraptor alert")); // true
14console.log(dinoPattern.test("Brachiosaurus")); // false
15
16// (?:) - non-capturing group
17const efficientPattern = /(?:Mr|Mrs|Dr)\.?\s+(\w+)/;
18const title = "Dr. Grant";
19const nameMatch = title.match(efficientPattern);
20console.log(nameMatch[1]); // "Grant" (only name, not title)1// g - global (find all matches)
2console.log("Rex Rex Rex".match(/Rex/)); // ["Rex"] (only first)
3console.log("Rex Rex Rex".match(/Rex/g)); // ["Rex", "Rex", "Rex"]
4
5// i - ignore case
6console.log(/trex/i.test("T-REX")); // true
7console.log(/trex/.test("T-REX")); // false
8
9// m - multiline (^ and $ apply to each line)
10const multiline = `Sector 1: OK
11Sector 2: ALERT
12Sector 3: OK`;
13
14console.log(multiline.match(/^Sector/gm));
15// ["Sector", "Sector", "Sector"] (start of each line)
16
17// s - dotAll (. also matches newline)
18const withNewline = "Start\nEnd";
19console.log(/Start.End/.test(withNewline)); // false
20console.log(/Start.End/s.test(withNewline)); // true1// 1. Validate dinosaur IDs
2function validateDinoId(id) {
3 const pattern = /^[A-Z]{2,6}-d{3}$/;
4 return pattern.test(id);
5}
6
7console.log(validateDinoId("RAPTOR-001")); // true
8console.log(validateDinoId("TREX-15")); // false (need 3 digits)
9console.log(validateDinoId("BRACHI-042")); // true
10
11// 2. Parse security log entries
12function parseSecurityLog(logEntry) {
13 const pattern = /(?<date>d{4}-d{2}-d{2}) (?<time>d{2}:d{2}:d{2}) [(?<dinoId>[A-Z]+-d+)] STATUS: (?<status>w+)/;
14 const match = logEntry.match(pattern);
15
16 if (!match) return null;
17
18 const { date, time, dinoId, status } = match.groups;
19 return { date, time, dinoId, status };
20}
21
22const log = "2024-01-15 10:30:45 [RAPTOR-001] STATUS: escaped";
23const parsed = parseSecurityLog(log);
24console.log(parsed);
25// { date: "2024-01-15", time: "10:30:45", dinoId: "RAPTOR-001", status: "escaped" }
26
27// 3. Validate email
28function validateEmail(email) {
29 const pattern = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$/;
30 return pattern.test(email);
31}
32
33// 4. Extract GPS coordinates
34function extractCoordinates(text) {
35 const pattern = /LAT: (?<lat>-?d+.d+), LON: (?<lon>-?d+.d+)/g;
36 const matches = [...text.matchAll(pattern)];
37
38 return matches.map(m => ({
39 lat: parseFloat(m.groups.lat),
40 lon: parseFloat(m.groups.lon)
41 }));
42}
43
44// 5. Sanitize input
45function sanitizeInput(input) {
46 // Remove potentially dangerous characters
47 return input
48 .replace(/<script[^>]*>.*?</script>/gi, '')
49 .replace(/<[^>]*>/g, '')
50 .trim();
51}1// ✅ Compile pattern once, use many times
2const dinoIdPattern = /^[A-Z]{3}-\d{3}$/;
3
4function validateManyIds(ids) {
5 return ids.filter(id => dinoIdPattern.test(id));
6}
7
8// ❌ Don't create patterns in loops
9function badValidation(ids) {
10 return ids.filter(id => /^[A-Z]{3}-\d{3}$/.test(id)); // New RegExp on each iteration!
11}
12
13// ✅ Use non-capturing groups when you don't need groups
14const efficient = /(?:Mr|Mrs|Dr)\.\s+\w+/; // (?:...) doesn't create a capturing group
15
16// ✅ Avoid excessive backtracking
17// ❌ Bad: /.*foo/ (can be very slow)
18// ✅ Good: /[^f]*foo/ or use lazy quantifier /.*?foo/Regular expressions are a powerful but complex tool. Their main advantages in a Jurassic Park context:
/RAPTOR-d{3}/)/^[A-Z]{2,6}-d{3}$/)match, matchAll with groups)replace)split)Key tips: use
test() for simple checks, match()/matchAll() for extraction, replace() for transformations, and always test your patterns on real data before deploying them to production!