Home / Blog / Regex

Regular expressions

Regex Character Classes: Brackets and Ranges

Learn JavaScript character classes with tested identifier and Unicode examples, boundary checks, escaping rules and common matching mistakes.

Class Regex

A character class describes a set of possible characters at one position in a regular expression. In JavaScript, [abc] matches one a, b or c. It does not mean the three-character word abc. Use a quantifier after the class when you need more than one character, and anchors when the whole input must match.

Build and test a small identifier rule

Suppose an identifier must start with an ASCII letter and then contain at most seven letters, digits, underscores or hyphens. This deliberately restricted rule is suitable for a machine identifier, not every person’s name.

const identifier = /^[A-Za-z][A-Za-z0-9_-]{0,7}$/;
const examples = ["A1", "team_2", "9team", "team two", "ABCDEFGHI"];
console.log(examples.map(value => [value, identifier.test(value)]));
// A1: true; team_2: true; 9team: false;
// team two: false; ABCDEFGHI: false

The first class admits one letter. The second admits zero through seven following characters, so total length is one through eight. The start and end anchors prevent a valid substring from hiding an invalid prefix or suffix. Test a blank input, the shortest accepted input and both sides of the length boundary before using the expression in a form.

Ranges, complements and punctuation

A hyphen between suitable endpoints creates a range, as in [0-9]. Put a literal hyphen last or escape it when that makes the intended set clearer. A caret at the beginning of a class negates it: [^0-9] accepts a non-digit. The same caret outside the brackets is an anchor. These meanings depend on position, so moving punctuation can change the rule.

A dot inside an ordinary class is literal: [.] matches a period. A dot outside usually matches any character except line terminators unless dot-all behavior is enabled. Parentheses and the alternation bar also lose their grouping meaning inside an ordinary class. To match either the word cat or dog, use (?:cat|dog); [cat|dog] would instead select one character from that set, including a literal bar.

Choose an alphabet deliberately

[A-Z] describes ASCII capital letters. It is not a universal definition of letters. For user-facing words, Unicode property escapes can express broader categories:

const letters = /^\p{L}[\p{L}\p{M}]*$/u;
console.log(letters.test("José")); // true
console.log(letters.test("नमस्ते")); // true
console.log(letters.test("Team 2")); // false

The mark category allows combining marks after the initial letter. This example still excludes spaces, apostrophes and hyphens. It is therefore a demonstration of a character set, not a complete name validator. Decide the actual allowed structure instead of adding broad classes until a single example happens to pass. Unicode normalization is a separate decision; visually identical sequences can have different underlying code points.

Diagnose unexpected matches

  • Only part of an invalid string matches: add whole-input anchors if that is your requirement.
  • Spaces are unexpectedly accepted: inspect the class and any \s shorthand. Whitespace includes more than an ordinary space.
  • Repeated tests alternate results: avoid the stateful global or sticky flags when using one expression as a simple Boolean validator, or reset its index intentionally.
  • A pattern copied into code changes: string constructors need an extra level of backslash escaping compared with regex literals.

Keep parsing and validation separate

A character-class match says only that the tested pattern fits. It does not establish that an email address exists, a URL is trustworthy or a program is valid. Use a format parser for structured data. For extraction, decide what surrounding boundaries should prevent matching part of a larger token. Record the engine and flags alongside test cases because JavaScript, Python, PHP and other engines differ.

Literal versus constructor

A regex literal such as /\d+/ and a string passed to the RegExp constructor pass through different parsers. In a JavaScript string, write the backslash as \\ so the regex engine receives one backslash. Inspect the expression’s source property when debugging a dynamically built pattern. Never concatenate arbitrary user text as pattern syntax when you intend a literal search: metacharacters need appropriate escaping, and very large or complex patterns need resource limits.

References

MDN character classes and character-class syntax.