Character classes
Start with a concrete problem. You have a tracking code as a messy string, "[9241] 620-8837-04", and you want the bare digits: 9241620883704. The brackets, spaces, and dashes all have to go.
One clean way to do this is to describe the kind of character you care about instead of listing exact symbols. Keep the digits, drop everything else. Character classes are the tool for that.
A character class is a compact notation that matches any single character from a whole category. Instead of spelling out 0, 1, 2, …, you write one short escape that stands for “any digit”.
The digit class is written \d and matches any one digit. Here it is finding the first digit in the tracking code:
let str = "[9241] 620-8837-04";
let regexp = /\d/;
alert( str.match(regexp) ); // 9
Without the g flag, a regexp stops at the first hit. So \d here matches only the leading 7 and quits.
Add the g flag and the search sweeps the whole string, collecting every digit:
let str = "[9241] 620-8837-04";
let regexp = /\d/g;
alert( str.match(regexp) ); // array of matches: 9,2,4,1,6,2,0,8,8,3,7,0,4
// glue them into a digits-only tracking number:
alert( str.match(regexp).join('') ); // 9241620883704
The common classes
Digits are one category. There are a few more you’ll reach for constantly.
Here they are in more detail:
pattern:\d(from “digit”)A digit: any character from
0to9.
pattern:\s(from “space”)A whitespace character. That covers the ordinary space, tabs
\t, newlines\n, and a handful of rarer characters: the vertical tab\v, the form feed\f, and the carriage return\r.
pattern:\w(from “word”)A “word” character: a Latin letter, a digit, or the underscore
_. Letters from other scripts — Cyrillic, Hindi, Greek, and so on — are not part of\w. If you need those, you’ll want theuflag and Unicode properties, covered later in this course.
To feel where each class draws its boundary, pick a class below and watch which characters in the sample light up. The tab is drawn as → and each space as · so you can see them:
Because each class matches one character, you can chain them to describe a shape. The pattern pattern:\d\s\w reads as “a digit, then a whitespace character, then a word character” — it would match a substring like match:3 x.
A regexp freely mixes literal characters and character classes.
For example, pattern:USB\d matches the literal text USB followed by any digit:
let str = "Plug into USB3 here";
let regexp = /USB\d/
alert( str.match(regexp) ); // USB3
You can stack several classes together too:
alert( "We played Halo4 today".match(/\s\w\w\w\w\d/) ); // ' Halo4'
Each piece of the pattern lines up with exactly one character of the match. Walking through it left to right:
Try it yourself. Edit the text or the pattern, then read off the match. Notice how removing a class or a literal from the pattern changes what lines up:
Inverse classes
Every class has an inverse — the same letter, uppercased. Where \d matches a digit, \D matches everything that is not a digit. Flipping the case flips the meaning.
pattern:\DNon-digit: any character except
pattern:\d. A letter, a bracket, a space — anything but0–9.
pattern:\SNon-whitespace: any character except
pattern:\s, such as a letter or a digit.
pattern:\WNon-word character: anything outside
pattern:\w, such as a punctuation mark, a space, or a non-Latin letter.
Back to the tracking code. Earlier we kept the digits and joined them:
let str = "[9241] 620-8837-04";
alert( str.match(/\d/g).join('') ); // 9241620883704
The inverse class gives you a shorter route. Instead of collecting what you want, delete what you don’t: find every non-digit \D and replace it with an empty string.
let str = "[9241] 620-8837-04";
alert( str.replace(/\D/g, "") ); // 9241620883704
Same result, less work — no array to build, no join to call. When the “junk” is easier to describe than the “signal”, reach for the inverse class.
Type any messy number below and watch \D strip everything that isn’t a digit:
A dot is “any character”
The dot pattern:. is its own special class. It matches any single character except a newline.
alert( "Q".match(/./) ); // Q
It’s most useful as a placeholder in the middle of a pattern — a slot that says “one of something, I don’t care what”:
let regexp = /UI.5/;
alert( "UIX5".match(regexp) ); // UIX5
alert( "UI-5".match(regexp) ); // UI-5
alert( "UI 5".match(regexp) ); // UI 5 (a space counts as a character)
There’s a catch worth burning into memory: the dot means “any character”, but it still demands that a character be present. It is not “maybe a character” — the slot must be filled.
alert( "UI5".match(/UI.5/) ); // null — nothing sits between I and 5 for the dot to match
Dot as literally any character with the “s” flag
By default the dot draws one line in the sand: it will not match the newline character \n.
So pattern:X.Y wants an X, then any single non-newline character, then a Y. Put a newline in the gap and there’s no match:
alert( "X\nY".match(/X.Y/) ); // null (no match)
Often that’s not what you want — you’d like the dot to mean truly any character, newlines included. The s flag (“dotall” mode) does exactly that. Turn it on and the dot stops treating \n as special:
alert( "X\nY".match(/X.Y/s) ); // X\nY (match!)
Toggle the s flag below and watch the same pattern /A.B/ flip between null and a match against a string that has a newline in the middle:
Summary
The character classes covered here:
pattern:\d— digits.pattern:\D— non-digits.pattern:\s— whitespace: spaces, tabs, newlines.pattern:\S— everything exceptpattern:\s.pattern:\w— Latin letters, digits, and the underscore_.pattern:\W— everything exceptpattern:\w.pattern:.— any character, but only including newlines when thesflag is set.
That’s the core set, and it’s not the whole story. JavaScript stores strings in Unicode, and Unicode tags every character with properties: which script a letter belongs to, whether it’s punctuation, whether it’s a number, and more. Regular expressions can search by those properties too, but that needs the u flag — the subject of the next article.