If your child can recognise a word with a regular expression but cannot select it only when the right context appears, lookaround is the next useful idea. Regex lookahead and lookbehind become easier when the learner separates two jobs: checking a condition at a position and consuming the text that belongs in the result. That distinction can turn a confusing collection of brackets into a method the student can explain.
Regex lookahead checks the text after the current position, while lookbehind checks the text before it. These assertions can succeed or fail without adding the checked context to the matched text. This guide uses JavaScript regular expressions to teach positive and negative lookarounds, zero-width checks, boundary mistakes and reliable test cases. Examples use invented labels and small strings so that the mechanism stays visible.
For a Punggol family fitting coding enrichment alongside school and tuition, a good lesson should leave the learner able to predict the exact matched text, not merely whether a pattern finds something. Ask what is checked, what is consumed and which near-miss should fail. These activities support careful programming practice; they do not advertise a particular coding class or suggest that every school subject requires regular expressions.
Choose your next learning step
1. Establish what a regular expression is being asked to do
A regular expression describes a text pattern. The program can use it to search for a matching part of a string, test whether a pattern appears, or replace matched text. Those tasks are related, but they require different questions about the result.
Before adding lookaround, state the desired job in ordinary language. “Find the word ready only when it is immediately followed by a colon” is much clearer than “use lookahead.” The first statement identifies the target text and the context. The second names a tool without specifying its purpose.
In JavaScript, /ready/ can find the letters ready inside a longer string. It does not automatically require ready to be a separate word or require the whole input to equal ready. A learner who misses that distinction may later blame lookaround for a problem that began with an unanchored search.
Use a small fictional text such as "ready: pending ready?". Ask which parts should be selected and which should not. Under the stated job, only the first ready qualifies. The colon confirms the required context, but the result should contain ready alone.
This starting contract guides every later test. A pattern is not correct simply because it returns a match. It is correct for a stated job when the matches and nonmatches follow the intended rule.
2. Locate the current position
Regex matching can be understood as moving through positions in a string. A consuming part matches characters and advances the position. An assertion checks something at a position without consuming the characters it checks. Lookaround belongs to the second category.
For the string "ready:", matching ready moves from the beginning to the position just before the colon. A lookahead placed after ready checks the text beginning at that position. If it requires a colon, the condition succeeds while leaving the position unchanged.
The full matched text is therefore ready, not ready followed by a colon. The checked context still exists in the input, but it is outside the consumed match. This is the central idea to establish before teaching the four syntax forms.
A paper exercise can help. Write the characters with spaces between them and mark the current position between characters. Move the mark while matching letters, then hold it still while checking the assertion. The learner can see why a context condition need not appear in the result.
Do not confuse zero-width with no work. The engine may inspect substantial text to evaluate an assertion. Zero-width describes how much input the assertion consumes in the match, not a promise of zero computational cost.
3. Read positive lookahead
Positive lookahead has the form (?=pattern). It requires the specified pattern to match beginning at the current position. The assertion itself does not consume that matching context.
For the job introduced earlier, /ready(?=:)/g matches ready when a colon immediately follows. The g flag requests a global search through the string. The colon is checked inside the lookahead; it is not consumed as part of the matched ready.
const text = "ready: pending ready?";
console.log(text.match(/ready(?=:)/g)); // ['ready']
Compare this with /ready:/g, which consumes the colon and returns ready with its colon. Both patterns find the qualifying location in this small example, but they produce different matched text. That difference matters for extraction and replacement.
Ask the student to state the assertion's position. It comes after ready, so it checks after the last y. Moving the lookahead before ready would ask a different question. The syntax is not a decoration that can be placed anywhere without changing meaning.
A useful first practice set changes only the following character: ready with a colon, a question mark, a space or the end of input. The learner can predict which one meets the immediate-colon condition before running the code.
4. Read negative lookahead
Negative lookahead has the form (?!pattern). It succeeds when the specified pattern does not match beginning at the current position. Like positive lookahead, it does not consume the tested text.
The pattern /ready(?!:)/g matches ready when a colon does not immediately follow. In the string "ready: ready? ready", it selects the second and third occurrences. The final occurrence qualifies because no colon follows at the end of the string.
This is a local assertion. It does not mean “there is no colon anywhere later in the input.” A colon several characters later does not necessarily make the immediate negative check fail. The pattern inside the assertion determines how much of the following context is tested.
Use an example such as "ready now: move". The expression ready(?!:) can match ready because the next character is a space. If the intended rule is “reject ready whenever a colon occurs later on the same line,” that is a different condition and requires a different pattern or a different parsing approach.
The student should explain the word immediately in the task. Many regex errors are reading errors about where a condition applies. A careful ordinary-language contract is part of the technical solution.
5. Read positive lookbehind
Positive lookbehind has the form (?<=pattern). It requires the relevant preceding context to match before the current position, while leaving that context outside the consumed match. JavaScript engines with lookbehind support can use this form directly.
For /(?<=tag:)ready/g, the target is ready and the required prefix is tag followed by a colon. In "tag:ready other:ready", the expression selects only the ready after tag. The prefix confirms the condition but is not part of the returned match.
const text = "tag:ready other:ready";
console.log(text.match(/(?<=tag:)ready/g)); // ['ready']
Do not teach lookbehind as simply “the same pattern backwards.” Its role is to check preceding context, and the engine's evaluation details can matter for more complex captures. Begin with a short literal prefix whose meaning is unambiguous.
The learner should mark the position immediately before ready. The lookbehind checks the context ending at that position. The consuming ready then advances through its letters. This keeps the checked prefix and the selected target distinct.
If the student's environment does not support lookbehind, use a supported alternative and document the difference. Compatibility is a property of the actual runtime, not a reason to claim that a pattern works in every tool called regex.
6. Read negative lookbehind
Negative lookbehind has the form (?<!pattern). It succeeds when the specified preceding context does not match at the current position. It can express a local exclusion without including a prefix in the result.
For a simple letter target, /(?<!#)note/g selects note when it is not immediately preceded by a hash symbol. In "#note note", only the second note qualifies. The first fails at the position before n because the required excluded context is present.
The assertion does not by itself establish a word boundary. In "keynote", the same pattern can find the note suffix because the preceding character is y rather than a hash. If the intended task requires a standalone label, add the appropriate boundaries or use a clearer token rule.
This is a useful moment to teach composition. One condition can exclude a prefix, while another condition can define the target's boundaries. Each part should have a named job. Combining several unexplained symbols makes it harder to notice which requirement was forgotten.
For practice, test the target at the start of the input, after a space, after a hash and inside a longer word. These cases make the difference between prefix exclusion and whole-word recognition visible.
7. Keep the four forms in one model
The four forms answer two paired questions: does the context appear or not, and is that context ahead of or behind the current position? Positive lookahead requires following context. Negative lookahead excludes following context. Positive lookbehind requires preceding context. Negative lookbehind excludes preceding context.
Rather than memorising four unrelated tricks, build a small reading routine. First identify the current position. Then identify the direction of the check. Then identify whether the condition is positive or negative. Finally identify the consuming target outside the assertion.
Use one fixed word with different fictional punctuation contexts. For example, select note after an opening bracket, before a closing bracket, without a preceding hash or without a following question mark. Each request gives a precise role to the assertion.
Do not choose complicated real text for the first comparison. Short strings remove distractions about punctuation variants, line endings, spelling and Unicode. The learner can master the mechanism before expanding the input domain.
The syntax begins to feel less arbitrary when the student can say, “This part checks what comes before the target, and this part consumes the target.” That sentence is a useful tutoring milestone because it applies to new examples.
8. Distinguish the full match from a captured group
A consuming prefix can be used when lookbehind is unavailable, but the full match then includes that prefix. A captured group can extract the target separately. This is a useful alternative, provided the program handles the result correctly.
Compare /(?<=tag:)ready/ with /tag:(ready)/. The first expression's full match is ready. The second expression's full match is tag:ready, while captured group one is ready. These are different result structures even though both can help retrieve the same target text.
const result = /tag:(ready)/.exec("tag:ready");
console.log(result[0]); // tag:ready
console.log(result[1]); // ready
A student who prints only result zero will see the prefix and may think capturing has failed. The capture did work; the program read the full-match field rather than the group field. Teach the result structure alongside the pattern.
This distinction also matters for replacement. Replacing the full consuming match can remove the prefix unintentionally unless the replacement preserves it. Lookbehind can avoid consuming the prefix, but the right choice depends on the task and runtime.
Keep the alternative clear and honest. It is not universally identical to lookbehind in every pattern, especially when overlapping matches or more complex context matters. Use it for the stated simple extraction job and test the actual behaviour.
9. Explain why lookahead does not skip ahead
A lookahead begins its check at the current position. It does not automatically search the rest of the string for its pattern. In ready(?=:), a colon must begin immediately after ready. A colon after a space is not enough.
If the requirement permits spaces before the colon, the assertion must express those spaces. For a simple ASCII-space example, ready(?= *:) checks for zero or more ordinary spaces followed by a colon. The spaces and colon remain outside the consumed match.
Be careful with shorthand such as whitespace. In JavaScript, \s matches more than the ordinary space character and can include line terminators. If a task must stay on one line or permit only certain separators, choose the character set deliberately.
A learner should not copy a broad whitespace pattern simply because it works on one example. Ask what kinds of gap are allowed. A tab, a line break and an ordinary space may have different meanings in the input format.
This is where regex becomes a lesson in precise specification. The pattern can be correct for the wrong rule if the student has not decided what counts as acceptable context.
10. Separate search from whole-input validation
A search expression looks for a qualifying location anywhere in the input. A validation expression may need to require that the entire input follows a rule. Lookaround does not automatically turn a search into full-input validation.
Suppose a fictional classroom label must begin with a letter and contain only letters or digits. A pattern without appropriate boundaries can find an acceptable substring inside an unacceptable input. The program may report success even though the whole label violates the rule.
For the simple ASCII examples in this guide, use explicit start and end requirements when the task concerns the full input. Understand how flags such as multiline change anchor behaviour, and decide whether line terminators are permitted. Do not use a classroom pattern as a universal validator for names or identifiers.
The distinction is visible with "@@AB12!!". A search for letters followed by digits can find AB12. That does not mean the entire string is an acceptable label. A whole-input check must reject the surrounding punctuation under the stated rule.
A parent can ask the student to explain whether the program is finding a part or judging the whole. This ordinary-language question often reveals the exact missing technical condition.
11. Combine independent lookaheads at one position
Several lookaheads can check independent conditions at the same position without consuming input. This is useful when the task requires multiple properties of a candidate string, but each condition must be designed carefully.
For an invented ASCII classroom code, suppose the full input must contain at least one letter, at least one digit, and only uppercase letters or digits, with length four to eight. The lookaheads check required content, while the consuming portion enforces the allowed characters and length.
const classroomCode = /^(?=.*[A-Z])(?=.*[0-9])[A-Z0-9]{4,8}(?![\s\S])/;
console.log(classroomCode.test("AB12")); // true
console.log(classroomCode.test("ABCD")); // false
console.log(classroomCode.test("1234")); // false
console.log(classroomCode.test("A-12")); // false
These are dummy labels, not a recommended password policy. The pattern's domain is deliberately limited to short uppercase ASCII codes. It should not be promoted as an appropriate rule for people's names, secure authentication or all international text.
Ask the learner to identify which part enforces each requirement. The first lookahead requires a letter, the second a digit, and the final consuming character class with its repetition defines the whole code. The assertions alone do not restrict every character.
This decomposition makes the pattern teachable. If one test fails unexpectedly, the learner can investigate the requirement that governs that case rather than editing the whole expression at random.
12. Notice backtracking and partial-match traps
A pattern can backtrack to a shorter consumed match in order to satisfy a following assertion. That behaviour is often useful, but it can surprise learners who assume a greedy repetition must always keep the longest possible text.
Consider /\d+(?!\.)/ on "123.45". The learner may intend to reject the number before the decimal point. The engine can nevertheless find a shorter match, such as 12, because after those two digits the next character is 3 rather than a dot. The negative assertion succeeds at that shorter position.
The pattern can also find 45 later in the string. It does not establish a complete numeric-token boundary. The lesson is not that negative lookahead is unreliable. The pattern expressed a narrower local condition than the intended task.
For numeric extraction, define the full token and its boundaries, or use a suitable parser. If a small regex is used, test surrounding digits, decimal points, signs and punctuation explicitly. Do not label an expression a number validator merely because it contains a digit class.
A strong tutoring exercise asks the student to predict a failing example, inspect the actual match and explain the backtracking position. The unexpected output then becomes evidence about the pattern's meaning.
13. Build token boundaries that fit the data
The familiar word-boundary assertion \b is useful in some tasks, but it does not mean a universal boundary between human words in every language. It is defined through the engine's word-character behaviour. For JavaScript classroom examples, treat it as a technical boundary rather than a linguistic promise.
If the task concerns fictional comma-separated labels, the delimiter rule may be more informative than a word boundary. If the task concerns identifiers that permit underscores, an underscore belongs inside the token under that rule. If it concerns natural-language text, punctuation and Unicode requirements need more careful consideration.
An alternative is to describe the permitted characters and surrounding delimiters explicitly. That can make the pattern longer, but it makes the data contract visible. The right boundary is the one that matches the format, not the shortest familiar escape.
For practice, compare note in "note", "notebook", "note_1" and "(note)". Ask which are standalone tokens under the chosen rule before choosing a regex. The answer is not determined by the learner's preference after seeing the output.
This habit transfers well to school projects. Define the format, test the boundaries, and explain what the result can establish. The program should not quietly broaden a limited rule into a claim about all text.
14. Use lookaround for context-sensitive replacement
Lookaround can make a replacement target depend on surrounding text while preserving the context. Suppose an invented worksheet uses status:old and note:old, and the task is to replace old only after the literal prefix status followed by a colon.
The expression /(?<=status:)old/g consumes old while checking the prefix. Replacing the match with new leaves status and its colon intact. The note field is unchanged because its preceding context does not meet the assertion.
const text = "status:old note:old";
console.log(text.replace(/(?<=status:)old/g, "new"));
// status:new note:old
This example is a controlled text format, not a general parser for every document that happens to contain a colon. If values can contain escapes, nested structures or inconsistent spacing, a format-aware parser may be clearer and safer.
Before replacement, preview the matches. Keep the original text and compare the resulting string. A student should be able to state exactly which substrings changed and why the others remained unchanged.
For a home enrichment session, use invented text that can be freely edited. There is no need to practise on actual pupil records or important documents. The learning goal is precise transformation, and a tiny artificial example is sufficient.
15. Understand overlapping results with zero-width patterns
A lookahead can identify a pattern beginning at a position without consuming the pattern as the full match. This can be useful for overlapping occurrences. In the string banana, the substring ana begins at positions one and three, and the occurrences overlap.
The pattern /(?=(ana))/g is itself zero-width at each qualifying position, while its captured group contains ana. JavaScript's matchAll can expose the captured text and the starting index for both occurrences.
const text = "banana";
const results = [...text.matchAll(/(?=(ana))/g)];
console.log(results.map(m => [m.index, m[1]]));
// [[1, 'ana'], [3, 'ana']]
The full match is empty because the outer lookahead consumes nothing. The captured group supplies the text inspected inside it. This is a useful distinction between the width of the match and the availability of captured information.
Do not introduce overlapping extraction before ordinary lookahead is clear. Otherwise, the learner must understand captures, zero-width results and global iteration simultaneously. Use it as an extension after the student can explain the simpler ready-before-colon example.
When writing manual matching loops, zero-width matches require careful progress handling. Prefer a suitable built-in iteration method for this small lesson and understand its behaviour rather than writing an unchecked loop that may repeatedly visit the same position.
16. Use flags as part of the pattern's meaning
Flags change how a regular expression behaves. Global search affects repeated matching. Case-insensitive matching changes the treatment of case. Multiline affects anchors. Dot-all changes what a dot can match. Unicode-related flags can change interpretation and supported syntax.
A learner should write the flags beside the ordinary-language contract. If the task says ready and READY should both qualify, a case-sensitive example will not satisfy it. If the task is limited to one line, allowing dot to cross line boundaries may change the result.
Do not add every available flag by habit. Each flag should answer a requirement. A pattern that behaves correctly in one text editor can behave differently in a JavaScript program if the flags or engine differ.
For a teaching exercise, use the same small string and change one flag at a time. Predict the difference before running it. This isolates the effect and prevents a collection of simultaneous changes from concealing the deciding rule.
The important habit is to treat a regex as the pattern together with its flags, runtime and operation. A screenshot of the pattern alone may omit information needed to reproduce the result.
17. Check the actual regex engine
JavaScript, Python, spreadsheet functions, command-line tools and text editors do not all implement identical regex features. Syntax that works in one may be unsupported or have different constraints in another. Lookbehind is a particularly useful place to notice this.
This guide's executable examples use JavaScript. If a learner transfers them to Python, they should consult Python's regular-expression documentation rather than assume every lookbehind form is accepted. If they transfer them to an editor, they should identify the editor's search engine and enabled options.
A compatibility check should be concrete: the runtime accepts the pattern, the operation returns the expected match fields, and the chosen test strings behave as specified. Merely recognising the bracket syntax is not enough.
For Punggol families discussing support with a tutor, include the actual environment in the question. “This pattern fails in our JavaScript console” is more useful than “regex does not work.” The environment narrows the technical investigation.
The learner does not need to memorise every engine's differences. They need to know that differences exist and to verify the behaviour that their project relies on.
18. Read complex lookbehind cautiously
In JavaScript, lookbehind evaluation can involve matching backwards within the assertion, and this can affect the contents of captured groups when quantified parts are involved. A learner should not infer complex capture behaviour solely from a forward-looking reading of the expression.
For an introductory lesson, literal prefixes and small explicit character sets are usually clearer than elaborate quantified lookbehind. They let the student establish the context-checking model without learning several engine details at once.
When a project genuinely needs a complicated assertion, reduce it to a small reproducible example and inspect the full result structure. Identify which groups capture which parts. Consult the engine's reference and test the relevant edge cases.
Sometimes a consuming prefix with a captured target, or a simple preprocessing step, produces a more readable solution. Lookbehind is one tool, not a requirement for every context-sensitive text task. The student should be able to explain why it was chosen.
A tutor can model that judgement explicitly. The most impressive-looking pattern is not necessarily the most teachable or maintainable one. A precise, tested solution that another reader can understand is a better learning result.
19. Avoid patterns whose complexity hides the requirement
A regular expression becomes difficult to maintain when the learner cannot connect its parts to the stated rule. Several nested assertions, broad repetitions and optional groups can create interactions that are hard to predict.
Before extending a pattern, write the new requirement separately. Does the target need a different prefix, a permitted gap, a boundary or a whole-input restriction? Add only the part that addresses that requirement, then rerun the existing tests.
If the format has nested syntax, quoting, escaping or a structured grammar, consider a parser. Regex can still help recognise local tokens, but it should not be used to hide an increasingly complicated interpretation problem.
For a small student project, readability is an appropriate priority. A two-step solution that extracts a field and then checks its value can be easier to explain than a single dense expression. The code's purpose is to carry out the task reliably, not to win a contest for fewest characters.
The learner should be able to remove one assertion and predict which test changes. That is a practical check that the pattern has meaningful parts rather than a collection of copied symbols.
20. Build a test table before declaring success
A useful test table includes positive cases, negative cases and boundary cases. Positive cases should qualify under the ordinary-language rule. Negative cases should fail for a named reason. Boundary cases check beginnings, endings, adjacent punctuation and empty input where relevant.
For ready immediately before a colon, test "ready:", "ready?", "ready :", "already:" and "ready". Decide whether ready inside already should qualify. If not, the target needs a boundary condition in addition to lookahead.
For a target after tag followed by a colon, test "tag:ready", "other:ready", "tag: ready", "tag:ready?" and an empty string. The permitted spacing and target boundaries must be specified before the pattern is judged.
Record the expected matched text, not just true or false, for extraction tasks. A pattern that includes an unwanted delimiter can pass a Boolean test while failing the extraction requirement.
When a student finds a new failure, add it to the table after fixing the pattern. The table preserves the reason for the repair and protects the earlier behaviours from accidental regression.
21. An independent practice workshop
For the string "note] note? [note #note", design four small searches: note immediately before a closing bracket, note not immediately before a question mark, note immediately after an opening bracket, and note not immediately after a hash. State any additional word-boundary requirement separately.
The first search can use note(?=\]). The closing bracket is escaped so it is treated as the literal punctuation required by the example. The returned match excludes the bracket. The second uses note(?!\?) and checks only the immediate following question mark.
The third can use (?<=\[)note, checking the opening bracket before the target. The fourth can use (?<!#)note, excluding the immediate hash prefix. These are local context tests; none automatically validates the entire input format.
Now explain the difference between note(?=\]) and note\]. The former returns note alone, while the latter consumes and returns the closing bracket as well. The difference is the match boundary, not whether the punctuation exists in the source.
Finally, change the punctuation and create a fresh example without looking at the earlier patterns. The learner should identify the context requirement, choose its direction and polarity, then decide which text to consume. That is a stronger check than reproducing the workshop's exact expressions.
22. Plan short learning sessions around the student's week
Begin with a consuming match and a positive lookahead. In a second short session, introduce negative lookahead and immediate-context tests. Add literal-prefix lookbehind once the learner can identify the current position confidently.
Keep each session's goal observable. The student should predict the exact returned text and explain one rejected case. A large number of successful matches is less informative if the learner cannot explain what the assertions are checking.
For a Punggol family balancing schoolwork, CCA and travel, a small text experiment can be enough. Use invented labels, allow the child to make a prediction, run the code, and discuss the difference. The adult's role can be asking for a clear explanation rather than becoming the regex expert.
If tuition or enrichment support is being considered, bring the attempted pattern, the runtime, the test string, the expected match and the actual result. These five items make the learning question precise. A tutor can then identify whether the gap concerns assertions, boundaries, flags or the result structure.
Stop after a useful correction and an independent check. The next session can retrieve the repaired rule. There is no need to make a small technical misunderstanding into a long evening of frustrated experimentation.
23. Questions parents and learners often ask
Does lookaround remove the surrounding text? No. It checks context without including that context in the consumed match. A replacement may change the matched target, but the assertion itself does not delete input characters.
Can a lookahead capture text? Yes, a capturing group inside a successful positive assertion can make inspected text available in the match result. The assertion can still be zero-width as a whole. Captured information and consumed match width are different properties.
Does negative lookahead mean the text never appears anywhere? No. It rejects the pattern beginning at the current position under the assertion's definition. A broader exclusion must explicitly inspect the relevant broader region.
Is a working regex proof that the data is correct? Only for the rule actually checked. It does not establish facts about the source, meaning or completeness of a document beyond that rule. A format check is not a truth check.
Should every text task use regex? No. Literal string methods, structured parsers or explicit code can be clearer for some jobs. Mastery includes recognising when a regular expression is a suitable tool and when another approach is easier to verify.
24. Continue with references and a clear next question
The MDN lookahead reference explains the positive and negative following-context forms. The lookbehind reference addresses preceding context and the engine details that matter in more complex cases.
The MDN assertions guide connects lookaround to other zero-width checks. The regular-expression guide provides a wider reference for pattern construction, operations and flags.
For the learning arrangement, return to How Studying Works at eduKatePunggol. Keep the next question concrete: which context should be checked, which target should be returned, and which near-miss must fail?
The useful achievement is not a mysterious pattern that happens to run. It is a learner who can explain the current position, the checked condition and the consumed result, then demonstrate that explanation on a fresh example. That makes regex lookaround a manageable skill rather than a guessing exercise.
25. Keep repeated tests independent
A JavaScript regular expression with a global or sticky flag can retain a lastIndex value between operations such as test or exec. Reusing that object can therefore affect where a later search begins. A learner may see alternating results and mistakenly conclude that the lookahead itself is unpredictable.
For a validation task that asks a separate yes-or-no question about each complete input, a non-global pattern is often the simpler choice. Global search is useful when collecting several matches from one string, but it is not needed merely because a program checks several different inputs.
To see the distinction, create a global pattern for ready before a colon and call test repeatedly on the same short string. After a successful match, its search position advances. A later test may begin after the qualifying occurrence. Inspect lastIndex as part of the explanation rather than rewriting the assertion.
If the chosen operation requires a stateful pattern, manage that state deliberately. Reset lastIndex when appropriate, create a fresh pattern for an independent check, or use an operation whose iteration behaviour suits the job. The correct choice depends on the actual program.
This is a useful final debugging question for a tutor: does the unexpected result depend on what ran immediately before it? If yes, inspect state as well as syntax. The same pattern text can appear in a reused object and a fresh object, and those objects can begin searching from different positions.
26. Require a genuine end for strict classroom codes
A strict whole-input classroom-code rule should reject an extra trailing character, including a line terminator. In JavaScript, an ordinary dollar anchor can match before a final line terminator, so the exact end requirement deserves an explicit check. The code example here uses a final negative lookahead for any remaining character.
The character class [\s\S] includes whitespace and non-whitespace characters. At the position after the consumed code, (?![\s\S]) succeeds only when no further character remains. That makes the end condition suitable for the narrowly defined ASCII label exercise, with the stated flags.
Test a valid label with a trailing ordinary space, a trailing punctuation mark and a trailing line break. All should fail under the rule that every character must belong to the label. Then test the valid label alone to confirm that the repair has not rejected the intended case.
The point is not to memorise a new ending incantation. It is to connect the exact input requirement to a check that actually expresses it. A full-input validator and a search for an acceptable substring are different programs even when their examples initially look similar.
For a beginner, this can be an optional extension after ordinary lookaround is secure. For a project relying on strict validation, it is part of correctness. A teacher or tutor can choose the order of instruction while preserving the distinction in the final explanation.
Keep the test input visible, including escaped line endings when necessary. Invisible characters are still characters, and a clear representation prevents a learner from comparing two apparently identical strings without seeing the difference that matters.

