Character classes: one of these
Square brackets describe a single character by listing what it may be.
Brackets match exactly one character
Square brackets describe one character by listing the options. [aeiou] matches a single vowel — not a run of them. This trips people up often enough to be worth stating twice: a class is one character, however many you list inside it.
Ranges are shorthand for a run of the character set: [a-z] is every lowercase letter, [0-9] every digit, [a-zA-Z0-9] any letter or digit. The dash only means a range between two characters; first or last in the brackets it is just a dash, which is why [-a-z] is a valid way to include one.
Negation, and the trap in it
A caret immediately after the opening bracket inverts the class: [^0-9] matches any single character that is not a digit. Anywhere else in the brackets a caret is an ordinary caret.
The trap is that a negated class still has to match something. [^0-9] does not mean "no digit here" — it means "one character, and it is not a digit". Against the text "42" it fails at both positions, but against "4a" it matches the a.
The shorthands, and what they quietly include
\d is a digit, \w is a word character, \s is whitespace, and each has an inverse: \D, \W, \S. They are shorter and they read better, and they are worth knowing precisely.
\w is not "a letter". It is [A-Za-z0-9_] — digits and the underscore included, accented letters excluded. So \w+ will happily match "user_2" and will stop short on "café". If you are validating names, that matters; JavaScript's u flag with Unicode property escapes such as \p{L} is the honest tool for letters in any script.
\s covers more than a space: tabs, newlines, carriage returns and several Unicode spaces. That is usually what you want when trimming, and occasionally a surprise when you meant a literal space.
Worked examples
Match a single hex digit
/[0-9a-fA-F]/gAgainst:
Colour #3fB2z9Every character matches individually here except z — a class is one character at a time.
See what \w leaves out
/\w+/gAgainst:
user_2 café naïveIt matches user_2 in full, then caf, then na — the accented letters are outside \w.
Check yourself
Practice questions written for this lesson — not past exam papers.
Practise every question in this subject
How many characters does [abc] match?
Which of these does \w match?