Before this lesson

Understand character classes and anchors. Be ready to compare several matching results.

What you will be able to do

Control repetition and understand greedy versus lazy selection.

Understand the mechanism

* means zero or more, + one or more, ? zero or one, and {m,n} bounds repetition. A quantifier applies to the immediately preceding atom or group, not the entire pattern.

Greedy quantifiers first try more characters; a following ? makes a quantifier lazy, initially trying fewer. Both are constrained by the remaining pattern. Lazy does not mean no backtracking or automatically faster.

For content that cannot contain a closing bracket, an explicit negated class expresses the boundary more directly than .*. This exercise handles flat labels, not nested brackets or HTML.

Runnable example

const text = "[one] [two]";
console.log(JSON.stringify(text.match(/\[.*\]/g)));
console.log(JSON.stringify(text.match(/\[.*?\]/g)));
console.log(JSON.stringify(text.match(/\[[^\]\r\n]+\]/g)));
console.log(JSON.stringify(["", "a", "aaaa"].map(s => /^a{1,3}$/.test(s))));

Trace and verify

The greedy pattern spans from the first opening bracket to the final closing bracket. The other patterns return separate one and two labels. Repetition 1 to 3 rejects both empty input and four a characters.

Common mistakes and boundaries

.*? can still match empty content. Decide explicitly whether [] is valid, and whether a negated class should permit newlines.

Practice challenge

Modify the third pattern to allow an empty [] label.

Reference solution and reasoning

Replace + after the negated class with *. Both [] and [one] match, while line breaks remain excluded.

Further reading