You need to use a tempered greedy token:
When to Use this Technique
Suppose our boss now tells us that we still want to match up to and including {END}, but that we also need to avoid stepping over a {MID}
section, if it exists. Starting with the lazy dot-star version to ensure we match up to the {END}
delimiter, we can then temper the dot to ensure it doesn't roll over {MID}
:
{START}(?:(?!{MID}).)*?{END}
If more phrases must be avoided, we just add them to our tempered dot:
{START}(?:(?!{MID})(?!{RESTART}).)*?{END}
This is a useful technique to know about.
Use
from((?:(?!exclude|to|from).)*)to
Use DOTALL modifier if you need the dot to match newlines.
See the regex demo
See a related SO thread about a tempered greedy token.