The simplest possible regex is a literal: a sequence of ordinary characters that matches only that exact sequence, nothing more and nothing less. The pattern cat matches the three characters c, a, t, in that order, wherever they appear in the input.
/cat/.test("cat"); // true
/cat/.test("concatenate"); // true — "cat" appears inside the word
/cat/.test("Cat"); // false — case doesn't match
Notice two things in that demo: regex matching is a substring search by default, so cat matches inside concatenate and cats without needing to match the whole line — and it’s case-sensitive by default, so Cat (capital C) doesn’t match the lowercase pattern cat at all.
Case sensitivity and the i flag
Most regex engines are case-sensitive out of the box, which is usually what you want — but plenty of real-world text (usernames, form input, log files) has inconsistent capitalization. Adding the i flag tells the engine to treat uppercase and lowercase letters as equivalent while matching:
/cat/i.test("CAT"); // true, thanks to the i flag
/cat/i.test("Catalog"); // true — still just a substring search
With the gi flags together (global + case-insensitive), the demo finds all four occurrences of cat regardless of capitalization — including the one hiding inside catalog.
Not every character is literal
Twelve characters have special meaning in regex and are called metacharacters: . ^ $ * + ? ( ) [ ] { } | and the backslash \ itself. When you want to match one of these characters literally, you must escape it by putting a backslash in front of it.
The dot . is the one people trip over most often, because it silently means “match any single character” instead of “match a period”:
/3.14/.test("3.14"); // true — the dot matches the literal "."
/3.14/.test("3x14"); // also true! the dot matched "x" instead
/3\.14/.test("3x14"); // false — now it must be an actual period
Compare the two demos above: the unescaped 3.14 happily matches 3x14 and 3814 because the dot swallows any character, while the escaped 3\.14 only matches the exact string 3.14.
| Character | Special meaning | Escape to match literally |
|---|---|---|
. |
Any character | \. |
* |
Zero or more | \* |
? |
Zero or one | \? |
( ) |
Grouping | \( \) |
[ ] |
Character class | \[ \] |
\ |
Escape character | \\ |
Watch out
It’s easy to over-escape. Characters like letters, digits, spaces, and punctuation such as , ! @ have no special meaning and don’t need a backslash. Escaping something that isn’t a metacharacter (like \k) is usually harmless but adds noise — and in some engines, an unrecognized escape sequence can even throw an error.
Try it yourself
Change the second demo’s pattern from 3\.14 back to 3.14 (remove the escape) and watch which lines start matching that shouldn’t. Then try writing a pattern that literally matches the string "a+b" (a plus sign between two letters, not “one or more a’s followed by b”).
What should happen
Removing the escape turns the dot back into a wildcard, so it starts matching 3x14 and 3814 again. For the second part, + is a metacharacter (you’ll meet it properly in the quantifiers lesson), so to match a literal plus sign you need a\+b — otherwise the engine reads it as “one or more of the previous character.”
What’s next
Literals only get you exact matches. The next lesson introduces character classes — [...] — which let a single position in your pattern match any one of a whole set of characters.