snake_case Identifier Regex
Validates that a string is a lower_snake_case identifier: lowercase words separated by single underscores, with no leading, trailing, or doubled underscores.
Regex Pattern
^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$Pattern Breakdown
Hover over a token to see what it does.
| Token | Meaning |
|---|---|
| ^ | Anchors the match to the start of the string |
| [a-z] | The identifier must begin with a lowercase letter |
| [a-z0-9]* | Zero or more lowercase letters or digits completing the first word |
| (?: | Start of a non-capturing group for each additional underscore-separated word |
| _[a-z0-9]+ | An underscore followed by at least one lowercase letter or digit for the next word |
| )* | Closes the group and allows any number of additional words |
| $ | Anchors the match to the end of the string |
Detailed Explanation
What it does
This pattern checks that a string follows lower_snake_case naming: it must start with a lowercase letter, and every additional word is introduced by a single underscore followed by at least one lowercase letter or digit. Strings with uppercase letters, dashes, spaces, or double underscores are rejected.
Why it works
The leading [a-z][a-z0-9]* requires the identifier to open with a lowercase run, and the repeating group (?:_[a-z0-9]+)* only accepts an underscore when it's immediately followed by at least one word character, which is what rules out double underscores (an empty word between two underscores can't satisfy the + quantifier). The ^/$ anchors guarantee the whole string conforms, not just a substring.
Common use cases
- Linting Python or Ruby variable and function names against snake_case style guides
- Validating database column names or environment variable keys before use
- Enforcing consistent naming in code generators or ORMs that map to snake_case schemas
- Detecting camelCase or kebab-case names that should be converted to snake_case
Edge cases
- A single lowercase word with no underscore, like 'variable', is valid since the repeating group is optional
- Trailing digits, like 'value_1', are valid because digits are allowed within any word segment
- A leading underscore, like '_private', is rejected since the first character must be a lowercase letter, not an underscore
- Consecutive underscores, like 'snake__case', are rejected because an underscore must be immediately followed by at least one word character
Limitations
- Does not support SCREAMING_SNAKE_CASE constants, which use uppercase letters instead
- Does not support Unicode letters outside the basic a-z/0-9 ranges
- Cannot verify that the identifier is a valid, non-reserved word in a specific programming language
Interactive Tester
Edit the pattern or text below — matching runs live in your browser.
Test Cases
Editable — add your own inputs to see if they pass.
| Input | Expected | Result | |
|---|---|---|---|
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass | |||
| Pass |
Language Variants
Production-ready examples in 12 languages.
const snakeCaseRegex = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;
console.log(snakeCaseRegex.test('variable_name_123')); // trueCommon Mistakes
Writing [a-z0-9_]+ to 'match snake_case', which also accepts leading/trailing/doubled underscores like '_foo__bar_'
Fix: Structure the pattern as a required first word plus repeated (?:_[a-z0-9]+)* groups so underscores must be internal single separators
Forgetting to allow digits within words, causing valid identifiers like 'value_2' to be rejected
Fix: Include 0-9 in each word's character class, e.g. [a-z0-9]* and [a-z0-9]+
Using this pattern to also validate SCREAMING_SNAKE_CASE constants
Fix: Write a separate pattern like ^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)*$ for uppercase constant naming
Performance Notes
- Both quantified segments are non-overlapping character classes, so the engine matches in linear time with no catastrophic backtracking
- Anchoring with ^ and $ lets invalid identifiers fail fast on the very first character check
- Cheap enough to run per-keystroke in an editor, linter, or form validator without noticeable cost
Browser Compatibility
| Engine | Supported | Notes |
|---|---|---|
| Chrome | Yes | — |
| Firefox | Yes | — |
| Safari | Yes | — |
| Edge | Yes | — |
| Node.js | Yes | — |