Recent chats
ASKGEEZ Q&A GUIDETechnology & devices

Why does a regex character class match more than the characters I expected?

Quick answer

A character class matches one character from its set. A hyphen between two characters can define a range, so [A-z] is a range, not just the endpoints. To include a literal hyphen, put it first or last in the class, or escape it. In Python re and JavaScript’s non-v mode, [a-z-] allows lowercase letters or a hyphen. JavaScript v mode has additional escaping rules. [S1][S2]

LET’S WORK THROUGH IT

The question, the details, the next step.

Question

Why does [A-z] accept characters I didn’t mean to allow? I wanted letters, and I thought the class just listed the endpoints.

Geez

A character class matches one character from its set; it does not mean “either endpoint only.” A hyphen between two characters can define a range. That means [A-z] describes a range, not just A and z. The range may include characters you did not intend, depending on the characters between its endpoints. [S1][S2]

If you mean uppercase and lowercase English letters, write the two ranges explicitly: [A-Za-z]. This accepts one uppercase or lowercase English letter; it does not accept digits, spaces, or a hyphen. If you need a different set, list the characters you intend to allow and make sure your ranges cover only those characters. A class matches one character at a time; a quantifier is needed to match a run of characters.

Follow-up question

How do I allow a hyphen as well as lowercase letters? Is there a safe way to write that in both Python and JavaScript?

Geez

In Python re and JavaScript’s non-v regex mode, put a literal hyphen at the beginning or end of the class, or escape it. For lowercase English letters plus a hyphen, these patterns express the intended set:

  • Python: re.compile(r"[a-z-]+")
  • JavaScript: /[a-z-]+/

The class [a-z-] allows a lowercase letter or a hyphen in each position; + asks for one or more such characters. For example, it accepts abc, a-b, and -; it does not accept A or 7. [S1][S2]

These JavaScript placement examples are for non-v classes. JavaScript v mode has additional escaping rules, so do not assume the non-v punctuation rules apply there. [S2]

Follow-up question

What if I put the hyphen between letters, like [a-z-] versus [a-z-0-9]? And does ^ always mean “not” inside brackets?

Geez

In [a-z-], the hyphen comes after the range, so it is literal in Python and JavaScript’s non-v mode. But [a-z-0-9] does not safely express “lowercase letters, hyphen, and digits”: the hyphen between z and 0 is not at an edge. Use [a-z0-9-] instead. That class allows lowercase letters, digits, or a hyphen, one character per match. [S1][S2]

In Python, ^ negates the class only when it is first; elsewhere it is literal. [S1] The JavaScript source cited here does not establish the corresponding ^ rule, so check the rules for your JavaScript regex mode rather than assuming the Python detail applies.

Follow-up question

Can you give me a small checklist and a corrected example I can adapt without accidentally allowing extra characters?

Geez

Assuming you want one or more lowercase English letters, digits, or literal hyphens, use [a-z0-9-]+ in Python re or JavaScript non-v mode. It accepts team-7 and abc, but not Team-7 or team_7. These examples illustrate the pattern; decide which characters your own input should allow, especially if “letter” means more than English A–Z. [S1][S2]

Test at least one example from each category: intended letters, intended digits, a literal hyphen, and characters that must be rejected. The class itself matches one character; + allows a run of one or more accepted characters.

A practical checklist

  • Write down the exact characters that should be accepted before choosing a range.

  • Check whether each hyphen is intended as a range marker or a literal character.

  • Put a literal hyphen first or last in the class, or escape it for the regex mode you use.

  • Name the JavaScript regex mode; do not apply non-v placement guidance to v mode.

  • Test accepted and rejected examples, including punctuation near range endpoints.

A few more useful answers

Does `[a-z]` match the whole word?

No. A character class matches one character from its set. A quantifier such as + can allow a run of those characters.

Is `[a-z-]` a way to include a hyphen?

The cited Python and JavaScript non-v rules allow a hyphen at the end of the class. For JavaScript v mode, check its additional escaping rules instead of assuming this guidance applies. [S1][S2]

Does `^` negate a character class wherever it appears?

In Python, ^ negates the class only when it is first; elsewhere it is literal. The cited JavaScript information does not establish this detail, so check the rules for your JavaScript regex mode. [S1]

Sources

References used for this guide.

  1. [S1] Python 3.15.2: Regular expression operations
    docs.python.org · Checked
  2. [S2] MDN: JavaScript character classes
    developer.mozilla.org · Checked

YOUR QUESTION. YOUR DETAILS.

Let’s work through your situation.

Get a tailored answer or help with your next task. Starts at $1, with a quote before you pay.

Ask your own question
← Back to Geez at Work