Document Workflow

Test JavaScript regex against real multiline text

Reproduce JavaScript regex behavior on multiline logs and copied documents while separating g, m, and s, inspecting capture ranges, and screening expensive near-matches.

Written and tested by Published: Reviewed:

How this workflow was checked

To check “Extract ERROR and WARN fields from a copied log”, we used JavaScript Regex Tester with Worker Timeout and Capture Ranges with the guide's exact source data and applied “Establish a minimal flag baseline”. The output had to match the documented result; evidence for “Testing a simplified single line” and “Using g to solve a multiline anchor problem” was reviewed before recording the check.

The gm pattern returned two full matches, six numbered captures, four named captures, and no zero-length match; ERROR and WARN were included while INFO stayed out.

Problem

A pattern that succeeds on one short line can fail or overmatch after text is copied from logs, PDFs, code viewers, terminals, or tickets. Line numbers and indentation move anchors, g is confused with m, dot stops at line terminators unless s is selected, and a broad quantified branch may become extremely slow only on a long non-matching suffix. A reliable review preserves the real block, changes one flag at a time, checks exact captures and UTF-16 ranges, and tests both intended matches and realistic failures.

When to use this

  • A JavaScript pattern works on one line but misses or overmatches a pasted multiline block.
  • You need to decide whether ^ and $ target the whole string or each line.
  • Dot should either stop at line terminators or intentionally span them.
  • Copied logs, code, or PDF text contain line numbers, blank rows, indentation, or Unicode characters.
  • A pattern will be used for extraction or replacement and needs a long near-match performance check first.

Steps

  1. Step 1

    Preserve the failing block

    Keep an untouched copy and paste the complete text that failed, including original line breaks, blank rows, indentation, prefixes, and final line. Do not clean the input until the exact behavior has been recorded.

  2. Step 2

    Identify the pattern representation

    Confirm whether you have a raw pattern body, a /literal/flags form, or a quoted JavaScript or JSON string. The tester accepts the pattern body without slash delimiters or source-code quotes; normalize escaping before judging the expression.

  3. Step 3

    Establish a minimal flag baseline

    Start with only the flags required by the destination. Use g to retrieve repeated matches, then compare m off and on for ^ and $. Keep s off unless dot must include line terminators, and enable u when the production expression uses Unicode semantics.

  4. Step 4

    Run and inspect exact evidence

    Execute the worker test and review every highlighted full match, zero-width marker, numbered capture, and named capture. Treat each [start, end) value as a UTF-16 code-unit range and reproduce it with text.slice(start, end) when checking code.

  5. Step 5

    Classify copied-text noise separately

    If line numbers or empty rows are accidental source artifacts, record their effect first, then clean a duplicate with Remove Line Numbers or Remove Empty Lines and rerun the same pattern. Do not silently change the production input contract.

  6. Step 6

    Test failures and near-matches

    Add punctuation, missing delimiters, an unexpected Unicode value, a blank field, and a long prefix or suffix that almost matches. A one-second worker timeout is a warning to simplify the expression, not a result to ignore or retry until it happens to pass.

  7. Step 7

    Verify extraction or replacement in context

    After matches and captures are stable, test Text Find and Replace on a disposable sample or call the expression in the destination JavaScript runtime. Compare output, run project tests, and retain the pattern body, flags, representative inputs, ranges, and timeout result with the change.

Example

Extract ERROR and WARN fields from a copied log

Input

Pattern: ^(?<level>ERROR|WARN)\s+\[(?<service>[^\]]+)\]\s+(.+)$
Flags: gm
Text:
ERROR [billing] Payment failed for order 1042
INFO [api] Request completed
WARN [search] Slow query detected

Output

2 full matches, 6 numbered captures, 4 named captures, and 0 zero-width matches. ERROR and WARN are included, INFO is excluded. Confirm the UTF-16 ranges, then add malformed and long near-match lines before using the pattern in a parser.

Common mistakes

Testing a simplified single line

A one-line sample hides anchor, terminator, blank-row, repeated-match, and long-failure behavior. Use the original multiline block and keep a minimized case only as a second fixture.

Using g to solve a multiline anchor problem

g retrieves subsequent matches; it does not change ^ or $. Toggle m for line boundaries and s separately for dot crossing line terminators.

Cleaning line numbers before recording the failure

Source prefixes can be the reason an anchor fails. Capture the exact result first, then clean a copy so the transformation remains an explicit part of the workflow.

Reading offsets as grapheme positions

JavaScript ranges count UTF-16 code units. Emoji, combining sequences, and other graphemes can make visual character counts differ from match and capture offsets.

Ignoring a worker timeout

A timeout indicates that this input exceeded the one-second review budget. Reduce ambiguity, bound quantifiers, use a parser, or evaluate a safer engine before placing the pattern on an untrusted production path.

FAQ

What is the difference between g and m?

g lets repeated exec calls return later matches. m changes ^ and $ so they can match line boundaries inside the string. Many multiline extraction tasks need both, but they solve different problems.

When is the s flag needed?

Use s only when dot must include line terminators. It does not affect ^ and $, and a more explicit bounded class can be easier to review than a broad dot-all expression.

Should copied line numbers be removed?

Remove them only when they are source-interface noise rather than part of the actual input contract. Record the uncleaned result first and test the cleanup as a separate transformation.

Why do emoji change the reported index?

JavaScript reports UTF-16 code-unit offsets. An astral emoji commonly occupies two code units, while a rendered grapheme can contain several code points and code units.

Does the one-second worker limit prove the regex is safe?

No. It keeps this page responsive and exposes obvious expensive cases. Production safety still depends on input distribution, runtime, concurrency, pattern structure, and stricter resource controls.

What evidence should accompany a production regex change?

Keep the exact pattern body and flags, intended and rejected fixtures, match and capture ranges, Unicode cases, a long near-match, timeout behavior, replacement or extraction output, and destination-runtime tests without retaining sensitive text unnecessarily.