amflare
amflare

Reputation: 4113

How to multiline regex but stop after first match?

I need to match any string that has certain characteristics, but I think enabling the /m flag is breaking the functionality.

What I know:

  1. The string will start and end with quotation marks.
  2. The string will have the following words. "the", "fox", and "lazy".
  3. The string may have a line break in the middle.
  4. The string will never have an at sign (used in the regex statement)

My problem is, if I have the string twice in a single block of text, it returns once, matching everything between the first quote mark and last quote mark with the required words in-between.

Here is my regex:

/^"the[^@]*fox[^@]*lazy[^@]*"$/gim

And a Regex101 example.

Here is my understanding of the statement. Match where the string starts with "the and there is the word fox and lazy (in that order) somewhere before the string ends with ". Also ignore newlines and case-sensitivity.

The most common answer to limiting is (.*?) But it doesn't work with new lines. And putting [^@?]* doesn't work because it adds the ? to the list of things to ignore.

So how can I keep the "match everything until ___" from skipping until the last instance while still being able to ignore newlines?

This is not a duplicate of anything else I can find because this deals with multi-line matching, and those don't.

Upvotes: 1

Views: 3481

Answers (2)

Shiva127
Shiva127

Reputation: 2623

In your case, all your quantifiers need to be non-greedy so you can just use the flag ungreedy: U.

/^"the[^@]*fox[^@]*lazy[^@]*"$/gimU

Example on Regex101.

Upvotes: 3

amflare
amflare

Reputation: 4113

The answer, which was figured out while typing up this question, may seem ridiculously obvious.

Put the ? after the *, not inside the brackets. Parenthesis and Brackets are not analogous, and the ? should be relative to the *.

Corrected regex:

/^"the[^@]*?fox[^@]*?lazy[^@]*?"$/gim

Example from Regex101.

The long and the short of this is:

Non-greedy, multi-line matching can be achieved with [^@]*?

(substituting @ for something you don't want to match)

Upvotes: 1

Related Questions