Let’s learn about quantifiers in regular expressions.

Consider a scenario where you want to match a four-digit identification code. You know you can use the \d character class, so you might write that four times. And to avoid any extraneous characters, you’d include both the start and end anchors:

const regex = /^\d\d\d\d$/;

And this does work – it will match four numerical characters. But rather than having to write out the same class multiple times, you can give it a quantifier.

Quantifiers are defined by curly braces containing one or two numbers. Let’s use a quantifier in our pattern:

const regex = /^\d{4}$/;

Notice how our quantifier contains only the number 4. This syntax means “match the previous character exactly four times”. Let’s see how that behaves:

const regex = /^\d{4}$/;
console.log(regex.test("123")); // false
console.log(regex.test("1234")); // true
console.log(regex.test("12345")); // false
console.log(regex.test("123456")); // false
console.log(regex.test("1234567")); // false

The pattern only matches the string with exactly four digits, because we have used the anchors and our quantifier only allows exactly four digits. But maybe the identification code only needs to be a minimum of four digits.

To allow for four or more digits, add a comma after the number in your quantifier:

const regex = /^\d{4,}$/;

Now, our syntax allows the pattern to match four or more digits. Let’s test it:

const regex = /^\d{4,}$/;
console.log(regex.test("123")); // false
console.log(regex.test("1234")); // true
console.log(regex.test("12345")); // true
console.log(regex.test("123456")); // true
console.log(regex.test("1234567")); // true

A seven-digit identifier is rather long. These identifiers should have a maximum of 6 digits, and a minimum of 4 digits. To achieve this, you can add a second number to your quantifier after the comma:

const regex = /^\d{4,6}$/;

And now our pattern no longer matches the seven-digit identifier, because it is greater than our six-digit maximum.

const regex = /^\d{4,6}$/;
console.log(regex.test("123")); // false
console.log(regex.test("1234")); // true
console.log(regex.test("12345")); // true
console.log(regex.test("123456")); // true
console.log(regex.test("1234567")); // false

Note that you cannot use this syntax to set a maximum alone – you must always set a minimum. But if you set the minimum to 1, you can effectively achieve the same result.

We’ve received updated requirements from our users. Identifiers can now optionally start with a letter. We already know the character class for this, so let’s add that to our regular expression:

const regex = /^[a-zA-z]\d{4,6}$/;

But now we mandate the presence of a letter. How can we make it optional?

You could use the quantifier syntax with 0 as the minimum and 1 as the maximum:

const regex = /^[a-zA-Z]{0,1}\d{4,6}$/;

But there’s actually a special shorthand quantifier for a single optional character – the question mark (?). Let’s replace our quantifier with the question mark:

const regex = /^[a-zA-Z]?\d{4,6}$/;

We should validate the result:

const regex = /^[a-zA-Z]?\d{4,6}$/;
console.log(regex.test("123")); // false
console.log(regex.test("a1234")); // true
console.log(regex.test("12345")); // true
console.log(regex.test("az12345")); // false
console.log(regex.test("X123456")); // true
console.log(regex.test("1234567")); // false

Our pattern now allows for a single optional letter, followed by four to six digits.

Unfortunately, we’ve just realized we read the requirements wrong. We need to allow for any number of letters before the numbers. We can use our quantifier with a 0 minimum and no defined maximum:

const regex = /^[a-zA-Z]{0,}\d{4,6}$/;

But our pattern is getting long again. Thankfully, there’s another short-hand for “match the previous character zero or more times” – the asterisk (*) symbol. Let’s replace our quantifier with that in the pattern, and test it:

const regex = /^[a-zA-Z]*\d{4,6}$/;
console.log(regex.test("123")); // false
console.log(regex.test("a1234")); // true
console.log(regex.test("12345")); // true
console.log(regex.test("az12345")); // true
console.log(regex.test("X123456")); // true
console.log(regex.test("1234567")); // false

Now we successfully match any identifier with zero or more letters followed by four to six numbers. But it turns out this is crashing our system – we actually have to require at least one letter.

Again, we could use a quantifier with a minimum of one and no defined maximum, or we could use yet another special syntax – the plus (+) symbol:

const regex = /^[a-zA-Z]+\d{4,6}$/;
console.log(regex.test("123")); // false
console.log(regex.test("a1234")); // true
console.log(regex.test("12345")); // false
console.log(regex.test("az12345")); // true
console.log(regex.test("X123456")); // true
console.log(regex.test("1234567")); // false

Now the identifiers that do not start with at least one letter fail, regardless of how many numbers there are.

You can use quantifiers to greatly enhance the brevity and readability of your regular expressions.