[EDIT: I left this post for information on capture groups, but the main solution I gave was incorrect. (?:START)((?:[^S]|S[^T]|ST[^A]|STA[^R]|STAR[^T])*)(?:END) hit> as specified in comments will not work; I forgot that ignored characters cannot be dropped, and so you need something like ... |STA(?![^R])| to allow this character to be part of END, so something like STARTSTEND has failed; so this is clearly the best choice; the following should show the correct way to use capture groups ...]
The answer given with the "zero width negative view" operator "?!", With capture groups: (?:START)((?!.*START).*)(?:END) , which captures the inner text using $ 1 for replacement. If you want the START and END entries to be captured, you could do (START)((?!.*START).*)(END) , which gives $ 1 = START $ 2 = text and $ 3 = END or various other permutations by adding / removing () or ?: s.
Thus, if you use it to search and replace, you can do something like BEGIN $ 1FINISH. So, if you started with:
abcSTARTdefSTARTghiENDjkl
you would get ghi as capture group 1, and replacing BEGIN $ 1FINISH would give you the following:
abcSTARTdefBEGINghiFINISHjkl
which will allow you to change START / END tokens only with the correct setting of pairs.
Each (x) is a group, but I put (?:x) for each of them, except for the middle, which marks it as a group not related to capture; the only one that I left without ?: was in the middle; however, you could also capture BEGIN / END markers if you want to move them or do something.
For more information on Java regular expressions, see the Java regex documentation .
source share