Metacharacters are symbols with a special meaning inside a regex. They are what make patterns powerful, and also what makes searching for a literal dot or question mark tricky. This lesson maps every one and shows how to switch off their special meaning when you need the plain character.
| Symbol | Meaning | Lesson |
|---|---|---|
| . | Any character except a line break | here |
| | | OR: this or that | here |
| \ | Escape: next character is literal (or a shorthand like \d) | here |
| [ ] | Character class | Classes |
| ^ $ | Start / end of text | Assertions |
| ( ) | Group | Groups |
| * + ? { } | How many times | Quantifiers |
/c.t/.test("cat") // true
/c.t/.test("c9t") // true
/c.t/.test("c t") // true (a space is a character too)
/c.t/.test("ct") // false (the dot needs exactly one character)
/cat|dog|bird/.test("I have a dog") // true
"jpg png gif bmp".match(/jpg|png|gif/g) // ["jpg", "png", "gif"]
| splits the whole pattern unless you group it. /^cat|dog$/ means "starts with cat" OR "ends with dog," not "is exactly cat or dog." Use a group: /^(cat|dog)$/.
To search for an actual dot, question mark, or other metacharacter, put a backslash before it:
/3.14/.test("3514") // true (oops: . matched "5")
/3\.14/.test("3514") // false
/3\.14/.test("3.14") // true
/\$\d+/.test("$25") // true literal dollar sign, then digits
/\(\d{3}\)/ // literal parentheses around 3 digits: "(410)"
Characters that need escaping outside brackets:
. * + ? ^ $ { } ( ) | [ ] \ /
If you build a regex from text someone typed, any metacharacters in it will be treated as pattern symbols. Escape them first:
function escapeRegExp(text) {
return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
const search = "C++";
const re = new RegExp(escapeRegExp(search), "g");
"I like C++ and C#".match(re) // ["C++"]
$& means "the matched text," and "\\" is one backslash in a string. So each metacharacter gets a backslash put in front of it. Without this, new RegExp("C++") throws a SyntaxError.
RegExp.escape("C++") returns a safely escaped pattern string, so new RegExp(RegExp.escape(search), "g") does the same job as escapeRegExp. (It also escapes a leading letter or digit in an unusual way, like \x43 for C, which is still correct.) Older browsers do not have it, so the hand-written function is still worth knowing.
| \n | Line break |
| \t | Tab |
| \d \w \s (and \D \W \S) | Shorthand classes |
| \b \B | Word boundary (next lesson) |
"line1\nline2\nline3".split(/\n/) // ["line1", "line2", "line3"]
"name\tage\tcity".split(/\t/) // ["name", "age", "city"]
W3Schools groups the backslash shorthands with the metacharacters. Capital letters mean NOT:
const text = "Give 100%!";
console.log(text.match(/\d/g)); // digits
console.log(text.match(/\D/g)); // NOT digits (the space counts)
console.log(text.match(/\w/g)); // word characters
console.log(text.match(/\W/g)); // NOT word characters
console.log("Is this all there is?".match(/\s/g).length); // spaces
Every character has a number. You can match a character by that number, written in hexadecimal (base 16):
| \xhh | Two hex digits | \x6F is "o" |
| \uhhhh | Four hex digits | \u0057 is "W" |
| \u{h...} | Any number of hex digits (needs the u flag) | \u{1F600} is "😀" |
const s = "Visit W3Schools. Hello World!";
console.log(s.replace(/\x6F/g, "*"));
console.log(s.match(/\u0057/g));
console.log(/\u{1F600}/u.test("😀"));
\ddd, a character by its octal (base 8) number: /\101/ matches "A". This is a leftover from old JavaScript. It is easy to confuse with a group reference like \1 (RegExp Groups), and with the u flag it is not allowed at all: /\101/u is SyntaxError: Invalid regular expression: /\101/u: Invalid escape. Use \x41 or \u0041 instead.
Which pattern matches the exact text "1+1=2"?
/1+1=2//1\+1=2//1[+]1=2/+ means "one or more 1s," so it matches "11=2" but not "1+1=2". Escaping with a backslash or putting + in a class both make it literal.What does this log?
console.log(/^(cat|dog)$/.test("catalog"), /^cat|dog$/.test("catalog"));
false true. Without the group, the second pattern means "starts with cat" OR "ends with dog," and "catalog" starts with cat.What happens with new RegExp("C++")?
+ has nothing to repeat. Escape user input first with escapeRegExp or RegExp.escape.new RegExp("?") and read the error, then fix it with escapeRegExp$ and .